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((char)value[0]))
660 0 : daemon_local->flags.offlineLogstorageDelimiter = (char)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 : * Main function of tool.
1255 : */
1256 1 : int main(int argc, char* argv[])
1257 : {
1258 : char version[DLT_DAEMON_TEXTBUFSIZE];
1259 : char local_str[DLT_DAEMON_TEXTBUFSIZE];
1260 : DltDaemonLocal daemon_local;
1261 : DltDaemon daemon;
1262 : int back = 0;
1263 :
1264 : memset(&daemon_local, 0, sizeof(DltDaemonLocal));
1265 : memset(&daemon, 0, sizeof(DltDaemon));
1266 :
1267 : /* Command line option handling */
1268 1 : if ((back = option_handling(&daemon_local, argc, argv)) < 0) {
1269 0 : if (back != -2)
1270 0 : fprintf(stderr, "option_handling() failed!\n");
1271 :
1272 0 : return -1;
1273 : }
1274 :
1275 : /* Set protocol version from option, fallback to env or default */
1276 1 : if (daemon_local.flags.protocolVersion == DLTProtocolV1 || daemon_local.flags.protocolVersion == DLTProtocolV2) {
1277 0 : daemon.daemon_version = daemon_local.flags.protocolVersion;
1278 : } else {
1279 1 : daemon.daemon_version = DLTProtocolV1;
1280 : }
1281 :
1282 : /* Configuration file option handling */
1283 1 : if ((back = option_file_parser(&daemon_local)) < 0) {
1284 0 : if (back != -2)
1285 0 : fprintf(stderr, "option_file_parser() failed!\n");
1286 :
1287 0 : return -1;
1288 : }
1289 :
1290 : /* Initialize internal logging facility */
1291 1 : dlt_log_set_filename(daemon_local.flags.loggingFilename);
1292 1 : dlt_log_set_level(daemon_local.flags.loggingLevel);
1293 1 : DltReturnValue log_init_result = dlt_log_init_multiple_logfiles_support(
1294 1 : daemon_local.flags.loggingMode, daemon_local.flags.enableLoggingFileLimit, daemon_local.flags.loggingFileSize,
1295 : daemon_local.flags.loggingFileMaxSize);
1296 :
1297 1 : if (log_init_result != DLT_RETURN_OK) {
1298 0 : fprintf(stderr, "Failed to init internal logging\n");
1299 :
1300 : #ifdef WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK
1301 : if (daemon_local.flags.loggingMode == DLT_LOG_TO_FILE) {
1302 : fprintf(stderr, "Falling back to syslog mode\n");
1303 :
1304 : daemon_local.flags.loggingMode = DLT_LOG_TO_SYSLOG;
1305 : log_init_result = dlt_log_init(daemon_local.flags.loggingMode);
1306 : if (log_init_result != DLT_RETURN_OK) {
1307 : fprintf(
1308 : stderr,
1309 : "Failed to setup syslog logging, internal logs will "
1310 : "not be available\n");
1311 : }
1312 : }
1313 : #endif
1314 : }
1315 :
1316 : /* Print version information */
1317 1 : dlt_get_version(version, DLT_DAEMON_TEXTBUFSIZE);
1318 :
1319 1 : dlt_vlog(LOG_NOTICE, "Starting DLT Daemon; %s\n", version);
1320 1 : if (daemon.daemon_version == 2) {
1321 0 : dlt_vlog(LOG_INFO, "DLT protocol version: 2 (DLTv2)\n");
1322 : } else {
1323 1 : dlt_vlog(LOG_INFO, "DLT protocol version: 1 (DLTv1)\n");
1324 : }
1325 :
1326 1 : PRINT_FUNCTION_VERBOSE(daemon_local.flags.vflag);
1327 :
1328 : /* Make sure the parent user directory is created */
1329 : const char* dir_to_create;
1330 : #ifdef DLT_DAEMON_USE_FIFO_IPC
1331 : dir_to_create = dltFifoBaseDir;
1332 : #else
1333 : dir_to_create = DLT_USER_IPC_PATH;
1334 : #endif
1335 1 : if (dlt_mkdir_recursive(dir_to_create) != 0) {
1336 0 : dlt_vlog(LOG_ERR, "Base dir %s cannot be created!\n", dir_to_create);
1337 0 : return -1;
1338 : }
1339 :
1340 : /* --- Daemon init phase 1 begin --- */
1341 1 : if (dlt_daemon_local_init_p1(&daemon, &daemon_local, daemon_local.flags.vflag) == -1) {
1342 0 : dlt_log(LOG_CRIT, "Initialization of phase 1 failed!\n");
1343 0 : return -1;
1344 : }
1345 :
1346 : /* --- Daemon init phase 1 end --- */
1347 :
1348 1 : if (dlt_daemon_prepare_event_handling(&daemon_local.pEvent)) {
1349 : /* TODO: Perform clean-up */
1350 0 : dlt_log(LOG_CRIT, "Initialization of event handling failed!\n");
1351 0 : return -1;
1352 : }
1353 :
1354 : /* --- Daemon connection init begin */
1355 1 : if (dlt_daemon_local_connection_init(&daemon, &daemon_local, daemon_local.flags.vflag) == -1) {
1356 0 : dlt_log(LOG_CRIT, "Initialization of local connections failed!\n");
1357 0 : return -1;
1358 : }
1359 :
1360 : /* --- Daemon connection init end */
1361 :
1362 1 : if (dlt_daemon_init_runtime_configuration(&daemon, daemon_local.flags.ivalue, daemon_local.flags.vflag) == -1) {
1363 0 : dlt_log(LOG_ERR, "Could not load runtime config\n");
1364 0 : return -1;
1365 : }
1366 :
1367 : /*
1368 : * Load dlt-runtime.cfg if available.
1369 : * This must be loaded before offline setup
1370 : */
1371 1 : dlt_daemon_configuration_load(&daemon, daemon.runtime_configuration, daemon_local.flags.vflag);
1372 :
1373 : /* --- Daemon init phase 2 begin --- */
1374 1 : if (dlt_daemon_local_init_p2(&daemon, &daemon_local, daemon_local.flags.vflag) == -1) {
1375 0 : dlt_log(LOG_CRIT, "Initialization of phase 2 failed!\n");
1376 0 : return -1;
1377 : }
1378 :
1379 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
1380 : /* Load control app id level configuration file without setting `back` to
1381 : * prevent exit if file is missing */
1382 : if (app_id_default_log_level_config_parser(&daemon, &daemon_local) < 0) {
1383 : dlt_vlog(
1384 : LOG_WARNING,
1385 : "app_id_default_log_level_config_parser() failed, "
1386 : "no app specific log levels will be configured\n");
1387 : }
1388 : #endif
1389 :
1390 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
1391 : /* Load control trace load configuration file without setting `back` to prevent exit if file is missing */
1392 : pthread_rwlock_init(&trace_load_rw_lock, NULL);
1393 : if (trace_load_config_file_parser(&daemon, &daemon_local) < 0) {
1394 : dlt_vlog(LOG_WARNING, "trace_load_config_file_parser() failed, using defaults for all app ids!\n");
1395 : }
1396 : #endif
1397 :
1398 : /* --- Daemon init phase 2 end --- */
1399 :
1400 1 : if (daemon_local.flags.offlineLogstorageDirPath[0])
1401 1 : if (dlt_daemon_logstorage_setup_internal_storage(
1402 : &daemon, &daemon_local, daemon_local.flags.offlineLogstorageDirPath, daemon_local.flags.vflag)
1403 : == -1)
1404 0 : dlt_log(LOG_INFO, "Setting up internal offline log storage failed!\n");
1405 :
1406 : /* create fd for watchdog */
1407 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
1408 : {
1409 : char* watchdogUSec = getenv("WATCHDOG_USEC");
1410 : // set a sensible default, in case the environment variable is not set
1411 : unsigned int watchdogTimeoutSeconds = 30;
1412 :
1413 : dlt_log(LOG_DEBUG, "Systemd watchdog initialization\n");
1414 :
1415 : if (watchdogUSec) {
1416 : // WATCHDOG_USEC is the timeout in micrsoseconds
1417 : // divide this by 2*10^6 to get the interval in seconds
1418 : // 2 * because we notify systemd after half the timeout
1419 : watchdogTimeoutSeconds = (unsigned int)atoi(watchdogUSec) / 2000000;
1420 : }
1421 :
1422 : if (watchdogTimeoutSeconds == 0) {
1423 : dlt_log(LOG_WARNING, "Watchdog timeout is too small, need at least 1s, setting 30s timeout\n");
1424 : watchdogTimeoutSeconds = 30;
1425 : }
1426 :
1427 : daemon.watchdog_trigger_interval = watchdogTimeoutSeconds;
1428 : daemon.watchdog_last_trigger_time = 0U;
1429 : create_timer_fd(&daemon_local, watchdogTimeoutSeconds, watchdogTimeoutSeconds, DLT_TIMER_SYSTEMD);
1430 : }
1431 : #endif
1432 :
1433 : /* create fd for timer timing packets */
1434 1 : create_timer_fd(&daemon_local, 1, 1, DLT_TIMER_PACKET);
1435 :
1436 : /* create fd for timer ecu version */
1437 1 : if ((daemon_local.flags.sendECUSoftwareVersion > 0) || (daemon_local.flags.sendTimezone > 0))
1438 0 : create_timer_fd(&daemon_local, 60, 60, DLT_TIMER_ECU);
1439 :
1440 : /* initiate gateway */
1441 1 : if (daemon_local.flags.gatewayMode == 1) {
1442 0 : if (dlt_gateway_init(&daemon_local, daemon_local.flags.vflag) == -1) {
1443 0 : dlt_log(LOG_CRIT, "Failed to create gateway\n");
1444 0 : return -1;
1445 : }
1446 :
1447 : /* create gateway timer */
1448 0 : create_timer_fd(
1449 : &daemon_local, daemon_local.pGateway.interval, daemon_local.pGateway.interval, DLT_TIMER_GATEWAY);
1450 : }
1451 :
1452 : /* For offline tracing we still can use the same states */
1453 : /* as for socket sending. Using this trick we see the traces */
1454 : /* In the offline trace AND in the socket stream. */
1455 1 : if (daemon_local.flags.yvalue[0])
1456 0 : dlt_daemon_change_state(&daemon, DLT_DAEMON_STATE_SEND_DIRECT);
1457 : else
1458 1 : dlt_daemon_change_state(&daemon, DLT_DAEMON_STATE_BUFFER);
1459 :
1460 1 : dlt_daemon_init_user_information(
1461 : &daemon, &daemon_local.pGateway, daemon_local.flags.gatewayMode, daemon_local.flags.vflag);
1462 :
1463 : /*
1464 : * Check for app and ctx runtime cfg.
1465 : * These cfg must be loaded after ecuId and num_user_lists are available
1466 : */
1467 1 : if ((dlt_daemon_applications_load(&daemon, daemon.runtime_application_cfg, daemon_local.flags.vflag) == 0)
1468 0 : && (dlt_daemon_contexts_load(&daemon, daemon.runtime_context_cfg, daemon_local.flags.vflag) == 0))
1469 0 : daemon.runtime_context_cfg_loaded = 1;
1470 :
1471 1 : dlt_daemon_log_internal(
1472 : &daemon, &daemon_local, "Daemon launched. Starting to output traces...", DLT_LOG_INFO, DLT_DAEMON_APP_ID,
1473 : DLT_DAEMON_CTX_ID, daemon_local.flags.vflag);
1474 :
1475 : /* Even handling loop. */
1476 272 : while ((back >= 0) && (g_exit >= 0))
1477 271 : back = dlt_daemon_handle_event(&daemon_local.pEvent, &daemon, &daemon_local);
1478 :
1479 1 : snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "Exiting DLT daemon... [%d]", g_signo);
1480 1 : dlt_daemon_log_internal(
1481 : &daemon, &daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
1482 : daemon_local.flags.vflag);
1483 1 : dlt_vlog(LOG_NOTICE, "%s%s", local_str, "\n");
1484 :
1485 1 : dlt_daemon_local_cleanup(&daemon, &daemon_local, daemon_local.flags.vflag);
1486 :
1487 : #ifdef UDP_CONNECTION_SUPPORT
1488 : dlt_daemon_udp_close_connection();
1489 : #endif
1490 :
1491 1 : dlt_gateway_deinit(&daemon_local.pGateway, daemon_local.flags.vflag);
1492 :
1493 1 : dlt_daemon_free(&daemon, daemon_local.flags.vflag);
1494 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
1495 : dlt_trace_load_free(&daemon);
1496 : #endif
1497 :
1498 1 : dlt_log(LOG_NOTICE, "Leaving DLT daemon\n");
1499 :
1500 1 : dlt_log_free();
1501 :
1502 1 : return 0;
1503 :
1504 : } /* main() */
1505 : #endif
1506 :
1507 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
1508 : void dlt_trace_load_free(DltDaemon* daemon)
1509 : {
1510 : if (daemon->preconfigured_trace_load_settings != NULL) {
1511 : free(daemon->preconfigured_trace_load_settings);
1512 : daemon->preconfigured_trace_load_settings = NULL;
1513 : }
1514 : pthread_rwlock_destroy(&trace_load_rw_lock);
1515 : }
1516 : #endif
1517 :
1518 :
1519 1 : int dlt_daemon_local_init_p1(DltDaemon* daemon, DltDaemonLocal* daemon_local, int verbose)
1520 : {
1521 1 : PRINT_FUNCTION_VERBOSE(verbose);
1522 : int ret = DLT_RETURN_OK;
1523 :
1524 1 : if ((daemon == 0) || (daemon_local == 0)) {
1525 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_init_p1()\n");
1526 0 : return -1;
1527 : }
1528 :
1529 : #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE)
1530 : ret = sd_booted();
1531 :
1532 : if (ret == 0) {
1533 : dlt_log(LOG_CRIT, "System not booted with systemd!\n");
1534 : } else if (ret < 0) {
1535 : dlt_log(LOG_CRIT, "sd_booted failed!\n");
1536 : return -1;
1537 : } else {
1538 : dlt_log(LOG_INFO, "System booted with systemd\n");
1539 : }
1540 :
1541 : #endif
1542 :
1543 : #ifdef DLT_DAEMON_USE_FIFO_IPC
1544 :
1545 1 : if (dlt_daemon_create_pipes_dir(daemon_local->flags.userPipesDir) == DLT_RETURN_ERROR)
1546 : return DLT_RETURN_ERROR;
1547 :
1548 : #endif
1549 :
1550 : /* Check for daemon mode */
1551 1 : if (daemon_local->flags.dflag)
1552 0 : dlt_daemon_daemonize(daemon_local->flags.vflag);
1553 :
1554 : /* initialise structure to use DLT file */
1555 1 : ret = dlt_file_init(&(daemon_local->file), daemon_local->flags.vflag);
1556 :
1557 1 : if (ret == DLT_RETURN_ERROR) {
1558 0 : dlt_log(LOG_ERR, "Could not initialize file structure\n");
1559 : /* Return value ignored, dlt daemon will exit */
1560 0 : dlt_file_free(&(daemon_local->file), daemon_local->flags.vflag);
1561 0 : return ret;
1562 : }
1563 :
1564 1 : signal(SIGPIPE, SIG_IGN);
1565 :
1566 1 : signal(SIGTERM, dlt_daemon_signal_handler); /* software termination signal from kill */
1567 1 : signal(SIGHUP, dlt_daemon_signal_handler); /* hangup signal */
1568 1 : signal(SIGQUIT, dlt_daemon_signal_handler);
1569 1 : signal(SIGINT, dlt_daemon_signal_handler);
1570 : #ifdef __QNX__
1571 : signal(SIGUSR1, dlt_daemon_signal_handler); /* for timer threads */
1572 : #endif
1573 :
1574 1 : return DLT_RETURN_OK;
1575 : }
1576 :
1577 1 : int dlt_daemon_local_init_p2(DltDaemon* daemon, DltDaemonLocal* daemon_local, int verbose)
1578 : {
1579 1 : PRINT_FUNCTION_VERBOSE(verbose);
1580 :
1581 1 : if ((daemon == 0) || (daemon_local == 0)) {
1582 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_init_p2()\n");
1583 0 : return -1;
1584 : }
1585 :
1586 : /* Daemon data */
1587 1 : if (dlt_daemon_init(
1588 : daemon, daemon_local->RingbufferMinSize, daemon_local->RingbufferMaxSize, daemon_local->RingbufferStepSize,
1589 1 : daemon_local->flags.ivalue, daemon_local->flags.contextLogLevel, daemon_local->flags.contextTraceStatus,
1590 : daemon_local->flags.enforceContextLLAndTS, daemon_local->flags.vflag)
1591 : == -1) {
1592 0 : dlt_log(LOG_ERR, "Could not initialize daemon data\n");
1593 0 : return -1;
1594 : }
1595 :
1596 : /* init offline trace */
1597 1 : if (((daemon->mode == DLT_USER_MODE_INTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH))
1598 0 : && daemon_local->flags.offlineTraceDirectory[0]) {
1599 0 : if (multiple_files_buffer_init(
1600 0 : &(daemon_local->offlineTrace), daemon_local->flags.offlineTraceDirectory,
1601 : daemon_local->flags.offlineTraceFileSize, daemon_local->flags.offlineTraceMaxSize,
1602 0 : daemon_local->flags.offlineTraceFilenameTimestampBased, false, DLT_OFFLINETRACE_FILENAME_BASE,
1603 : DLT_OFFLINETRACE_FILENAME_EXT)
1604 : == -1) {
1605 0 : dlt_log(LOG_ERR, "Could not initialize offline trace\n");
1606 0 : return -1;
1607 : }
1608 : }
1609 :
1610 : /* Init offline logstorage for MAX devices */
1611 1 : if (daemon_local->flags.offlineLogstorageMaxDevices > 0) {
1612 1 : size_t max_devices = (size_t)daemon_local->flags.offlineLogstorageMaxDevices;
1613 1 : daemon->storage_handle = malloc(sizeof(DltLogStorage) * max_devices);
1614 :
1615 1 : if (daemon->storage_handle == NULL) {
1616 0 : dlt_log(LOG_ERR, "Could not initialize offline logstorage\n");
1617 0 : return -1;
1618 : }
1619 :
1620 : memset(daemon->storage_handle, 0, sizeof(DltLogStorage) * max_devices);
1621 : }
1622 :
1623 : /* Set ECU id of daemon */
1624 1 : if (daemon_local->flags.evalue[0]) {
1625 0 : dlt_set_id(daemon->ecuid, daemon_local->flags.evalue);
1626 0 : daemon->ecuid2len = (uint8_t)strlen(daemon_local->flags.evalue);
1627 0 : dlt_set_id_v2(daemon->ecuid2, daemon_local->flags.evalue, daemon->ecuid2len);
1628 :
1629 : } else {
1630 1 : dlt_set_id(daemon->ecuid, DLT_DAEMON_ECU_ID);
1631 1 : daemon->ecuid2len = (uint8_t)strlen(DLT_DAEMON_ECU_ID);
1632 1 : dlt_set_id_v2(daemon->ecuid2, DLT_DAEMON_ECU_ID, daemon->ecuid2len);
1633 : }
1634 :
1635 : /* Set flag for optional sending of serial header */
1636 1 : daemon->sendserialheader = daemon_local->flags.lflag;
1637 :
1638 : #ifdef DLT_SHM_ENABLE
1639 :
1640 : /* init shared memory */
1641 : if (dlt_shm_init_server(
1642 : &(daemon_local->dlt_shm), daemon_local->flags.dltShmName, daemon_local->flags.sharedMemorySize)
1643 : == DLT_RETURN_ERROR) {
1644 : dlt_log(LOG_ERR, "Could not initialize shared memory\n");
1645 : return -1;
1646 : }
1647 :
1648 : daemon_local->recv_buf_shm = (unsigned char*)calloc(1, DLT_SHM_RCV_BUFFER_SIZE);
1649 :
1650 : if (NULL == daemon_local->recv_buf_shm) {
1651 : dlt_log(LOG_ERR, "failed to allocated the buffer to receive shm data\n");
1652 : return -1;
1653 : }
1654 :
1655 : #endif
1656 :
1657 : /* prepare main loop */
1658 1 : if (dlt_message_init(&(daemon_local->msg), daemon_local->flags.vflag) == DLT_RETURN_ERROR) {
1659 0 : dlt_log(LOG_ERR, "Could not initialize message\n");
1660 0 : return -1;
1661 : }
1662 :
1663 : /* configure sending timing packets */
1664 1 : if (daemon_local->flags.sendMessageTime)
1665 0 : daemon->timingpackets = 1;
1666 :
1667 1 : if (dlt_daemon_local_ecu_version_init(daemon, daemon_local, daemon_local->flags.vflag) < 0) {
1668 1 : daemon->ECUVersionString = malloc(DLT_DAEMON_TEXTBUFSIZE);
1669 :
1670 1 : if (daemon->ECUVersionString == 0) {
1671 0 : dlt_log(LOG_WARNING, "Could not allocate memory for version string\n");
1672 0 : return -1;
1673 : }
1674 :
1675 1 : dlt_get_version(daemon->ECUVersionString, DLT_DAEMON_TEXTBUFSIZE);
1676 : }
1677 :
1678 : /* Set to allows one to maintain logstorage loglevel as default */
1679 1 : daemon->maintain_logstorage_loglevel = DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_ON;
1680 :
1681 1 : return 0;
1682 : }
1683 :
1684 1 : static int dlt_daemon_init_serial(DltDaemonLocal* daemon_local)
1685 : {
1686 : /* create and open serial connection from/to client */
1687 : /* open serial connection */
1688 : int fd = -1;
1689 :
1690 1 : if (daemon_local->flags.yvalue[0] == '\0')
1691 : return 0;
1692 :
1693 0 : fd = open(daemon_local->flags.yvalue, O_RDWR);
1694 :
1695 0 : if (fd < 0) {
1696 0 : dlt_vlog(LOG_ERR, "Failed to open serial device %s\n", daemon_local->flags.yvalue);
1697 :
1698 0 : daemon_local->flags.yvalue[0] = 0;
1699 0 : return -1;
1700 : }
1701 :
1702 0 : if (isatty(fd)) {
1703 : int speed = DLT_DAEMON_SERIAL_DEFAULT_BAUDRATE;
1704 :
1705 0 : if (daemon_local->flags.bvalue[0])
1706 0 : speed = atoi(daemon_local->flags.bvalue);
1707 :
1708 0 : daemon_local->baudrate = dlt_convert_serial_speed(speed);
1709 :
1710 0 : if (dlt_setup_serial(fd, (speed_t)daemon_local->baudrate) < 0) {
1711 0 : close(fd);
1712 0 : daemon_local->flags.yvalue[0] = 0;
1713 :
1714 0 : dlt_vlog(
1715 0 : LOG_ERR, "Failed to configure serial device %s (%s) \n", daemon_local->flags.yvalue, strerror(errno));
1716 :
1717 0 : return -1;
1718 : }
1719 :
1720 0 : if (daemon_local->flags.vflag)
1721 0 : dlt_log(LOG_DEBUG, "Serial init done\n");
1722 : } else {
1723 0 : close(fd);
1724 0 : fprintf(
1725 0 : stderr, "Device is not a serial device, device = %s (%s) \n", daemon_local->flags.yvalue, strerror(errno));
1726 0 : daemon_local->flags.yvalue[0] = 0;
1727 0 : return -1;
1728 : }
1729 :
1730 0 : return dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_CLIENT_MSG_SERIAL);
1731 : }
1732 :
1733 : #ifdef DLT_DAEMON_USE_FIFO_IPC
1734 1 : static int dlt_daemon_init_fifo(DltDaemonLocal* daemon_local)
1735 : {
1736 : int ret;
1737 : int fd = -1;
1738 : #ifdef __linux__
1739 : int fifo_size;
1740 : #endif
1741 :
1742 : /* open named pipe(FIFO) to receive DLT messages from users */
1743 1 : umask(0);
1744 :
1745 : /* Try to delete existing pipe, ignore result of unlink */
1746 1 : const char* tmpFifo = daemon_local->flags.daemonFifoName;
1747 1 : unlink(tmpFifo);
1748 :
1749 1 : ret = mkfifo(tmpFifo, S_IRUSR | S_IWUSR | S_IWGRP);
1750 :
1751 1 : if (ret == -1) {
1752 0 : dlt_vlog(LOG_WARNING, "FIFO user %s cannot be created (%s)!\n", tmpFifo, strerror(errno));
1753 0 : return -1;
1754 : } /* if */
1755 :
1756 : /* Set group of daemon FIFO */
1757 1 : if (daemon_local->flags.daemonFifoGroup[0] != 0) {
1758 0 : errno = 0;
1759 0 : struct group* group_dlt = getgrnam(daemon_local->flags.daemonFifoGroup);
1760 :
1761 0 : if (group_dlt) {
1762 0 : ret = chown(tmpFifo, (uid_t)-1, group_dlt->gr_gid);
1763 :
1764 0 : if (ret == -1)
1765 0 : dlt_vlog(
1766 : LOG_ERR, "FIFO user %s cannot be chowned to group %s (%s)\n", tmpFifo,
1767 : daemon_local->flags.daemonFifoGroup, strerror(errno));
1768 0 : } else if ((errno == 0) || (errno == ENOENT) || (errno == EBADF) || (errno == EPERM)) {
1769 0 : dlt_vlog(
1770 : LOG_ERR, "Group name %s is not found (%s)\n", daemon_local->flags.daemonFifoGroup, strerror(errno));
1771 : } else {
1772 0 : dlt_vlog(
1773 : LOG_ERR, "Failed to get group id of %s (%s)\n", daemon_local->flags.daemonFifoGroup, strerror(errno));
1774 : }
1775 : }
1776 :
1777 : fd = open(tmpFifo, O_RDWR);
1778 :
1779 1 : if (fd == -1) {
1780 0 : dlt_vlog(LOG_WARNING, "FIFO user %s cannot be opened (%s)!\n", tmpFifo, strerror(errno));
1781 0 : return -1;
1782 : } /* if */
1783 :
1784 : #ifdef __linux__
1785 : /* F_SETPIPE_SZ and F_GETPIPE_SZ are only supported for Linux.
1786 : * For other OSes it depends on its system e.g. pipe manager.
1787 : */
1788 1 : if (daemon_local->daemonFifoSize != 0) {
1789 : /* Set Daemon FIFO size */
1790 0 : if (fcntl(fd, F_SETPIPE_SZ, daemon_local->daemonFifoSize) == -1)
1791 0 : dlt_vlog(LOG_ERR, "set FIFO size error: %s\n", strerror(errno));
1792 : }
1793 :
1794 : /* Get Daemon FIFO size */
1795 1 : if ((fifo_size = fcntl(fd, F_GETPIPE_SZ, 0)) == -1)
1796 0 : dlt_vlog(LOG_ERR, "get FIFO size error: %s\n", strerror(errno));
1797 : else
1798 1 : dlt_vlog(LOG_INFO, "FIFO size: %d\n", fifo_size);
1799 : #endif
1800 :
1801 : /* Early init, to be able to catch client (app) connections
1802 : * as soon as possible. This registration is automatically ignored
1803 : * during next execution.
1804 : */
1805 1 : return dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_APP_MSG);
1806 : }
1807 : #endif
1808 :
1809 : #ifdef DLT_DAEMON_VSOCK_IPC_ENABLE
1810 : static int dlt_daemon_init_vsock(DltDaemonLocal* daemon_local)
1811 : {
1812 : int fd;
1813 : struct sockaddr_vm addr;
1814 :
1815 : fd = socket(AF_VSOCK, SOCK_STREAM, 0);
1816 : if (fd == -1) {
1817 : dlt_vlog(LOG_ERR, "Failed to create VSOCK socket: %s\n", strerror(errno));
1818 : return -1;
1819 : }
1820 :
1821 : memset(&addr, 0, sizeof(addr));
1822 : addr.svm_family = AF_VSOCK;
1823 : addr.svm_port = DLT_VSOCK_PORT;
1824 : addr.svm_cid = VMADDR_CID_ANY;
1825 :
1826 : if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
1827 : dlt_vlog(LOG_ERR, "Failed to bind VSOCK socket: %s\n", strerror(errno));
1828 : close(fd);
1829 : return -1;
1830 : }
1831 :
1832 : if (listen(fd, 1) != 0) {
1833 : dlt_vlog(LOG_ERR, "Failed to listen on VSOCK socket: %s\n", strerror(errno));
1834 : close(fd);
1835 : return -1;
1836 : }
1837 :
1838 : return dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_APP_CONNECT);
1839 : }
1840 : #endif
1841 :
1842 : #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC
1843 : static DltReturnValue dlt_daemon_init_app_socket(DltDaemonLocal* daemon_local)
1844 : {
1845 : /* socket access permission set to srw-rw-rw- (666) */
1846 : int mask = S_IXUSR | S_IXGRP | S_IXOTH;
1847 : DltReturnValue ret = DLT_RETURN_OK;
1848 : int fd = -1;
1849 :
1850 : if (daemon_local == NULL) {
1851 : dlt_vlog(LOG_ERR, "%s: Invalid function parameters\n", __func__);
1852 : return DLT_RETURN_ERROR;
1853 : }
1854 :
1855 : #ifdef ANDROID
1856 : /* on android if we want to use security contexts on Unix sockets,
1857 : * they should be created by init (see dlt-daemon.rc in src/daemon)
1858 : * and recovered through the below API */
1859 : ret = dlt_daemon_unix_android_get_socket(&fd, daemon_local->flags.appSockPath);
1860 : if (ret < DLT_RETURN_OK) {
1861 : /* we failed to get app socket created by init.
1862 : * To avoid blocking users to launch dlt-daemon only through
1863 : * init on android (e.g: by hand for debugging purpose), try to
1864 : * create app socket by ourselves */
1865 : ret = dlt_daemon_unix_socket_open(&fd, daemon_local->flags.appSockPath, SOCK_STREAM, mask);
1866 : }
1867 : #else
1868 : ret = dlt_daemon_unix_socket_open(&fd, daemon_local->flags.appSockPath, SOCK_STREAM, mask);
1869 : #endif
1870 : if (ret == DLT_RETURN_OK) {
1871 : if (dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_APP_CONNECT)) {
1872 : dlt_log(LOG_CRIT, "Could not create connection for app socket.\n");
1873 : return DLT_RETURN_ERROR;
1874 : }
1875 : } else {
1876 : dlt_log(LOG_CRIT, "Could not create and open app socket.\n");
1877 : return DLT_RETURN_ERROR;
1878 : }
1879 :
1880 : return ret;
1881 : }
1882 : #endif
1883 :
1884 1 : static DltReturnValue dlt_daemon_initialize_control_socket(DltDaemonLocal* daemon_local)
1885 : {
1886 : /* socket access permission set to srw-rw---- (660) */
1887 : int mask = S_IXUSR | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
1888 : DltReturnValue ret = DLT_RETURN_OK;
1889 1 : int fd = -1;
1890 :
1891 1 : if (daemon_local == NULL) {
1892 0 : dlt_vlog(LOG_ERR, "%s: Invalid function parameters\n", __func__);
1893 0 : return -1;
1894 : }
1895 :
1896 : #ifdef ANDROID
1897 : /* on android if we want to use security contexts on Unix sockets,
1898 : * they should be created by init (see dlt-daemon.rc in src/daemon)
1899 : * and recovered through the below API */
1900 : ret = dlt_daemon_unix_android_get_socket(&fd, daemon_local->flags.ctrlSockPath);
1901 : if (ret < DLT_RETURN_OK) {
1902 : /* we failed to get app socket created by init.
1903 : * To avoid blocking users to launch dlt-daemon only through
1904 : * init on android (e.g by hand for debugging purpose), try to
1905 : * create app socket by ourselves */
1906 : ret = dlt_daemon_unix_socket_open(&fd, daemon_local->flags.ctrlSockPath, SOCK_STREAM, mask);
1907 : }
1908 : #else
1909 1 : ret = dlt_daemon_unix_socket_open(&fd, daemon_local->flags.ctrlSockPath, SOCK_STREAM, mask);
1910 : #endif
1911 1 : if (ret == DLT_RETURN_OK) {
1912 1 : if (dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_CONTROL_CONNECT)
1913 : < DLT_RETURN_OK) {
1914 0 : dlt_log(LOG_ERR, "Could not initialize control socket.\n");
1915 : ret = DLT_RETURN_ERROR;
1916 : }
1917 : }
1918 :
1919 : return ret;
1920 : }
1921 :
1922 1 : int dlt_daemon_local_connection_init(DltDaemon* daemon, DltDaemonLocal* daemon_local, int verbose)
1923 : {
1924 1 : int fd = -1;
1925 :
1926 1 : PRINT_FUNCTION_VERBOSE(verbose);
1927 :
1928 1 : if ((daemon == NULL) || (daemon_local == NULL)) {
1929 0 : dlt_vlog(LOG_ERR, "%s: Invalid function parameters\n", __func__);
1930 0 : return -1;
1931 : }
1932 :
1933 1 : DltBindAddress_t* head = daemon_local->flags.ipNodes;
1934 :
1935 : #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC
1936 : /* create and open socket to receive incoming connections from user application */
1937 : if (dlt_daemon_init_app_socket(daemon_local) < DLT_RETURN_OK) {
1938 : dlt_log(LOG_ERR, "Unable to initialize app socket.\n");
1939 : return DLT_RETURN_ERROR;
1940 : }
1941 :
1942 : #else /* DLT_DAEMON_USE_FIFO_IPC */
1943 :
1944 1 : if (dlt_daemon_init_fifo(daemon_local)) {
1945 0 : dlt_log(LOG_ERR, "Unable to initialize fifo.\n");
1946 0 : return DLT_RETURN_ERROR;
1947 : }
1948 :
1949 : #endif
1950 :
1951 : #ifdef DLT_DAEMON_VSOCK_IPC_ENABLE
1952 : if (dlt_daemon_init_vsock(daemon_local) != 0) {
1953 : dlt_log(LOG_ERR, "Unable to initialize app VSOCK socket.\n");
1954 : return DLT_RETURN_ERROR;
1955 : }
1956 : #endif
1957 :
1958 : /* create and open socket to receive incoming connections from client */
1959 1 : daemon_local->client_connections = 0;
1960 :
1961 1 : if (head == NULL) { /* no IP set in BindAddress option, will use "0.0.0.0" as default */
1962 :
1963 1 : if (dlt_daemon_socket_open(&fd, daemon_local->flags.port, "0.0.0.0") == DLT_RETURN_OK) {
1964 1 : if (dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_CLIENT_CONNECT)) {
1965 0 : dlt_log(LOG_ERR, "Could not initialize main socket.\n");
1966 0 : return DLT_RETURN_ERROR;
1967 : }
1968 : } else {
1969 0 : dlt_log(LOG_ERR, "Could not initialize main socket.\n");
1970 0 : return DLT_RETURN_ERROR;
1971 : }
1972 : } else {
1973 : bool any_open = false;
1974 0 : while (head != NULL) { /* open socket for each IP in the bindAddress list */
1975 :
1976 0 : if (dlt_daemon_socket_open(&fd, daemon_local->flags.port, head->ip) == DLT_RETURN_OK) {
1977 0 : if (dlt_connection_create(
1978 : daemon_local, &daemon_local->pEvent, fd, POLLIN, DLT_CONNECTION_CLIENT_CONNECT)) {
1979 0 : dlt_vlog(LOG_ERR, "Could not create connection, for binding %s\n", head->ip);
1980 : } else {
1981 : any_open = true;
1982 : }
1983 : } else {
1984 0 : dlt_vlog(LOG_ERR, "Could not open main socket, for binding %s\n", head->ip);
1985 : }
1986 :
1987 0 : head = head->next;
1988 : }
1989 :
1990 0 : if (!any_open) {
1991 0 : dlt_vlog(LOG_ERR, "Failed create main socket for any configured binding\n");
1992 0 : return DLT_RETURN_ERROR;
1993 : }
1994 : }
1995 :
1996 : #ifdef UDP_CONNECTION_SUPPORT
1997 :
1998 : if (daemon_local->UDPConnectionSetup == MULTICAST_CONNECTION_ENABLED) {
1999 : if (dlt_daemon_udp_connection_setup(daemon_local) < 0) {
2000 : dlt_log(LOG_ERR, "UDP fd creation failed\n");
2001 : return DLT_RETURN_ERROR;
2002 : } else {
2003 : dlt_log(LOG_INFO, "UDP fd creation success\n");
2004 : }
2005 : }
2006 :
2007 : #endif
2008 :
2009 : /* create and open unix socket to receive incoming connections from
2010 : * control application */
2011 1 : if (dlt_daemon_initialize_control_socket(daemon_local) < DLT_RETURN_OK) {
2012 0 : dlt_log(LOG_ERR, "Could not initialize control socket.\n");
2013 0 : return DLT_RETURN_ERROR;
2014 : }
2015 :
2016 : /* Init serial */
2017 1 : if (dlt_daemon_init_serial(daemon_local) < 0) {
2018 0 : dlt_log(LOG_ERR, "Could not initialize daemon data\n");
2019 0 : return DLT_RETURN_ERROR;
2020 : }
2021 :
2022 : return 0;
2023 : }
2024 :
2025 0 : static char* file_read_everything(FILE* const file, const size_t sizeLimit)
2026 : {
2027 0 : if (!file) {
2028 : return NULL;
2029 : }
2030 :
2031 : /* Get the file size. Bail out if stat fails. */
2032 0 : const int fd = fileno(file);
2033 0 : struct stat s_buf = {0};
2034 0 : if (fstat(fd, &s_buf) < 0) {
2035 0 : dlt_log(LOG_WARNING, "failed to stat file size\n");
2036 0 : fclose(file);
2037 0 : return NULL;
2038 : }
2039 :
2040 : /* Size limit includes NULL terminator. */
2041 0 : const off_t size = s_buf.st_size;
2042 0 : if (size < 0 || (size_t)size >= sizeLimit) {
2043 0 : dlt_log(LOG_WARNING, "file size invalid\n");
2044 0 : fclose(file);
2045 0 : return NULL;
2046 : }
2047 :
2048 0 : char* const string = malloc((size_t)size + 1);
2049 0 : if (!string) {
2050 0 : dlt_log(LOG_WARNING, "failed to allocate string for file contents\n");
2051 0 : fclose(file);
2052 0 : return NULL;
2053 : }
2054 :
2055 : off_t offset = 0;
2056 0 : while (!feof(file)) {
2057 0 : offset += (off_t)fread(string + offset, 1, (size_t)size, file);
2058 :
2059 0 : if (ferror(file)) {
2060 0 : dlt_log(LOG_WARNING, "failed to read file\n");
2061 0 : free(string);
2062 0 : fclose(file);
2063 0 : return NULL;
2064 : }
2065 :
2066 0 : if (offset > size) {
2067 0 : dlt_log(LOG_WARNING, "file too long for buffer\n");
2068 0 : free(string);
2069 0 : fclose(file);
2070 0 : return NULL;
2071 : }
2072 : }
2073 :
2074 0 : string[offset] = '\0'; /* append null termination at end of string */
2075 :
2076 0 : return string;
2077 : }
2078 :
2079 0 : static char* file_read_field(FILE* const file, const char* const fieldName)
2080 : {
2081 0 : if (!file) {
2082 : return NULL;
2083 : }
2084 :
2085 : const char* const kDelimiters = "\r\n\"\'=";
2086 0 : const size_t fieldNameLen = strlen(fieldName);
2087 :
2088 : char* result = NULL;
2089 :
2090 0 : char* buffer = NULL;
2091 0 : size_t bufferSize = 0;
2092 :
2093 : while (true) {
2094 : ssize_t lineSize = getline(&buffer, &bufferSize, file);
2095 0 : if (lineSize < 0 || !buffer) {
2096 : /* end of file */
2097 : break;
2098 : }
2099 :
2100 : char* line = buffer;
2101 :
2102 : /* trim trailing delimiters */
2103 0 : while (lineSize >= 1 && strchr(kDelimiters, line[lineSize - 1]) != NULL) {
2104 0 : line[lineSize - 1] = '\0';
2105 0 : --lineSize;
2106 : }
2107 :
2108 : /* check fieldName */
2109 0 : if (strncmp(line, fieldName, fieldNameLen) == 0 && (size_t)lineSize >= (fieldNameLen + 1)
2110 0 : && strchr(kDelimiters, line[fieldNameLen]) != NULL) {
2111 : /* trim fieldName */
2112 : line += fieldNameLen;
2113 :
2114 : /* trim delimiter */
2115 0 : ++line;
2116 :
2117 : /* trim leading delimiters */
2118 0 : while (*line != '\0' && strchr(kDelimiters, *line) != NULL) {
2119 0 : ++line;
2120 : --lineSize;
2121 : }
2122 :
2123 0 : result = strdup(line);
2124 0 : break;
2125 : }
2126 : }
2127 :
2128 0 : free(buffer);
2129 :
2130 0 : return result;
2131 : }
2132 :
2133 1 : int dlt_daemon_local_ecu_version_init(DltDaemon* daemon, DltDaemonLocal* daemon_local, int verbose)
2134 : {
2135 : FILE* f = NULL;
2136 :
2137 1 : PRINT_FUNCTION_VERBOSE(verbose);
2138 :
2139 : /* By default, version string is null. */
2140 1 : daemon->ECUVersionString = NULL;
2141 :
2142 : /* Open the file. Bail out if error occurs */
2143 1 : f = fopen(daemon_local->flags.pathToECUSoftwareVersion, "r");
2144 :
2145 1 : if (f == NULL) {
2146 : /* Error level notice, because this might be deliberate choice */
2147 1 : dlt_log(LOG_NOTICE, "Failed to open ECU Software version file.\n");
2148 1 : return -1;
2149 : }
2150 :
2151 0 : if (daemon_local->flags.ecuSoftwareVersionFileField[0] != '\0') {
2152 0 : daemon->ECUVersionString = file_read_field(f, daemon_local->flags.ecuSoftwareVersionFileField);
2153 : } else {
2154 0 : daemon->ECUVersionString = file_read_everything(f, DLT_DAEMON_TEXTBUFSIZE);
2155 : }
2156 :
2157 0 : fclose(f);
2158 :
2159 0 : return (daemon->ECUVersionString != NULL) ? 0 : -1;
2160 : }
2161 :
2162 1 : void dlt_daemon_local_cleanup(DltDaemon* daemon, DltDaemonLocal* daemon_local, int verbose)
2163 : {
2164 1 : PRINT_FUNCTION_VERBOSE(verbose);
2165 :
2166 1 : if ((daemon == 0) || (daemon_local == 0)) {
2167 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_cleanup()\n");
2168 0 : return;
2169 : }
2170 :
2171 : /* Don't receive event anymore */
2172 1 : dlt_event_handler_cleanup_connections(&daemon_local->pEvent);
2173 :
2174 1 : dlt_message_free(&(daemon_local->msg), daemon_local->flags.vflag);
2175 1 : dlt_message_free_v2(&(daemon_local->msgv2), daemon_local->flags.vflag);
2176 :
2177 : /* free shared memory */
2178 1 : if (daemon_local->flags.offlineTraceDirectory[0])
2179 0 : multiple_files_buffer_free(&(daemon_local->offlineTrace));
2180 :
2181 : /* Ignore result */
2182 1 : dlt_file_free(&(daemon_local->file), daemon_local->flags.vflag);
2183 :
2184 : #ifdef DLT_DAEMON_USE_FIFO_IPC
2185 : /* Try to delete existing pipe, ignore result of unlink() */
2186 1 : unlink(daemon_local->flags.daemonFifoName);
2187 : #else /* DLT_DAEMON_USE_UNIX_SOCKET_IPC */
2188 : /* Try to delete existing pipe, ignore result of unlink() */
2189 : if (unlink(daemon_local->flags.appSockPath) != 0) {
2190 : dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n", __func__, strerror(errno));
2191 : }
2192 : #endif
2193 :
2194 : #ifdef DLT_SHM_ENABLE
2195 : /* free shared memory */
2196 : dlt_shm_free_server(&(daemon_local->dlt_shm), daemon_local->flags.dltShmName);
2197 : free(daemon_local->recv_buf_shm);
2198 : daemon_local->recv_buf_shm = NULL;
2199 : #endif
2200 :
2201 1 : if (daemon_local->flags.offlineLogstorageMaxDevices > 0) {
2202 : /* disconnect all logstorage devices */
2203 1 : dlt_daemon_logstorage_cleanup(daemon, daemon_local, daemon_local->flags.vflag);
2204 :
2205 1 : free(daemon->storage_handle);
2206 : }
2207 :
2208 1 : if (daemon->ECUVersionString != NULL)
2209 1 : free(daemon->ECUVersionString);
2210 :
2211 1 : if (unlink(daemon_local->flags.ctrlSockPath) != 0) {
2212 0 : dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n", __func__, strerror(errno));
2213 : }
2214 :
2215 : /* free IP list */
2216 1 : free(daemon_local->flags.ipNodes);
2217 : }
2218 :
2219 0 : void dlt_daemon_exit_trigger()
2220 : {
2221 : /* stop event loop */
2222 0 : g_exit = -1;
2223 :
2224 : #ifdef DLT_DAEMON_USE_FIFO_IPC
2225 0 : char tmp[DLT_PATH_MAX] = {0};
2226 :
2227 : ssize_t n;
2228 0 : n = snprintf(tmp, DLT_PATH_MAX, "%s/dlt", dltFifoBaseDir);
2229 0 : if (n < 0 || (size_t)n > DLT_PATH_MAX) {
2230 0 : dlt_vlog(LOG_WARNING, "%s: snprintf truncation/error(%ld) %s\n", __func__, (long int)n, tmp);
2231 : }
2232 :
2233 0 : (void)unlink(tmp);
2234 : #endif
2235 :
2236 : #ifdef __QNX__
2237 : dlt_daemon_cleanup_timers();
2238 : #endif
2239 0 : }
2240 :
2241 0 : void dlt_daemon_signal_handler(int sig)
2242 : {
2243 0 : g_signo = sig;
2244 :
2245 0 : switch (sig) {
2246 0 : case SIGHUP:
2247 : case SIGTERM:
2248 : case SIGINT:
2249 : case SIGQUIT: {
2250 : /* finalize the server */
2251 0 : dlt_vlog(LOG_NOTICE, "Exiting DLT daemon due to signal: %s\n", strsignal(sig));
2252 0 : dlt_daemon_exit_trigger();
2253 0 : break;
2254 : }
2255 : default: {
2256 : /* This case should never happen! */
2257 : break;
2258 : }
2259 : } /* switch */
2260 :
2261 0 : } /* dlt_daemon_signal_handler() */
2262 :
2263 : #ifdef __QNX__
2264 : void dlt_daemon_cleanup_timers()
2265 : {
2266 : int i = 0;
2267 : while (i < DLT_TIMER_UNKNOWN) {
2268 : /* Remove FIFO of every timer and kill timer thread */
2269 : if (0 != timer_threads[i]) {
2270 : pthread_kill(timer_threads[i], SIGUSR1);
2271 : pthread_join(timer_threads[i], NULL);
2272 : timer_threads[i] = 0;
2273 :
2274 : close_pipes(dlt_timer_pipes[i]);
2275 :
2276 : /* Free data of every timer */
2277 : if (NULL != timer_data[i]) {
2278 : free(timer_data[i]);
2279 : timer_data[i] = NULL;
2280 : }
2281 : }
2282 : i++;
2283 : }
2284 : }
2285 : #endif
2286 :
2287 0 : void dlt_daemon_daemonize(int verbose)
2288 : {
2289 : int i;
2290 : int fd;
2291 :
2292 0 : PRINT_FUNCTION_VERBOSE(verbose);
2293 :
2294 0 : dlt_log(LOG_NOTICE, "Daemon mode\n");
2295 :
2296 : /* Daemonize */
2297 0 : i = fork();
2298 :
2299 0 : if (i < 0) {
2300 0 : dlt_log(LOG_CRIT, "Unable to fork(), exiting DLT daemon\n");
2301 0 : exit(-1); /* fork error */
2302 : }
2303 :
2304 0 : if (i > 0)
2305 0 : exit(0); /* parent exits */
2306 :
2307 : /* child (daemon) continues */
2308 :
2309 : /* Process independency */
2310 :
2311 : /* obtain a new process group */
2312 0 : if (setsid() == -1) {
2313 0 : dlt_log(LOG_CRIT, "setsid() failed, exiting DLT daemon\n");
2314 0 : exit(-1); /* fork error */
2315 : }
2316 :
2317 : /* Open standard descriptors stdin, stdout, stderr */
2318 : fd = open("/dev/null", O_RDWR);
2319 :
2320 0 : if (fd != -1) {
2321 : /* Redirect STDOUT to /dev/null */
2322 0 : if (dup2(fd, STDOUT_FILENO) < 0)
2323 0 : dlt_vlog(LOG_WARNING, "Failed to direct stdout to /dev/null. Error: %s\n", strerror(errno));
2324 :
2325 : /* Redirect STDERR to /dev/null */
2326 0 : if (dup2(fd, STDERR_FILENO) < 0)
2327 0 : dlt_vlog(LOG_WARNING, "Failed to direct stderr to /dev/null. Error: %s\n", strerror(errno));
2328 :
2329 0 : close(fd);
2330 : } else {
2331 0 : dlt_log(LOG_CRIT, "Error opening /dev/null, exiting DLT daemon\n");
2332 0 : exit(-1); /* fork error */
2333 : }
2334 :
2335 : /* Set umask */
2336 0 : umask(DLT_DAEMON_UMASK);
2337 :
2338 : /* Change to root directory */
2339 0 : if (chdir("/") < 0)
2340 0 : dlt_log(LOG_WARNING, "Failed to chdir to root\n");
2341 :
2342 : /* Catch signals */
2343 0 : signal(SIGCHLD, SIG_IGN); /* ignore child */
2344 0 : signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
2345 0 : signal(SIGTTOU, SIG_IGN);
2346 0 : signal(SIGTTIN, SIG_IGN);
2347 :
2348 0 : } /* dlt_daemon_daemonize() */
2349 :
2350 : /* This function logs str to the configured output sink (socket, serial, offline trace).
2351 : * To avoid recursion this function must be called only from DLT highlevel functions.
2352 : * E. g. calling it to output a failure when the open of the offline trace file fails
2353 : * would cause an endless loop because dlt_daemon_log_internal() would itself again try
2354 : * to open the offline trace file.
2355 : * This is a dlt-daemon only function. The libdlt has no equivalent function available. */
2356 : /* TODO: How to call when it doesn't has version info */
2357 4 : int dlt_daemon_log_internal(
2358 : DltDaemon* daemon, DltDaemonLocal* daemon_local, char* str, DltLogLevelType level, const char* app_id,
2359 : const char* ctx_id, int verbose)
2360 : {
2361 : static uint8_t uiMsgCount = 0;
2362 4 : if (daemon->daemon_version == 2) {
2363 : DltMessageV2 msg;
2364 0 : if (dlt_message_init_v2(&msg, 0) == DLT_RETURN_ERROR)
2365 0 : return DLT_RETURN_ERROR;
2366 :
2367 : uint32_t uiType;
2368 : uint16_t uiSize;
2369 : char ecid_buf[DLT_V2_ID_SIZE];
2370 : char apid_buf[DLT_V2_ID_SIZE];
2371 : char ctid_buf[DLT_V2_ID_SIZE];
2372 :
2373 : DltHtyp2ContentType msgcontent = DLT_VERBOSE_DATA_MSG;
2374 :
2375 0 : PRINT_FUNCTION_VERBOSE(verbose);
2376 :
2377 0 : msg.storageheadersizev2 = (uint32_t)(STORAGE_HEADER_V2_FIXED_SIZE + strlen(DLT_DAEMON_ECU_ID));
2378 0 : msg.baseheadersizev2 = BASE_HEADER_V2_FIXED_SIZE;
2379 0 : msg.baseheaderextrasizev2 = (int32_t)dlt_message_get_extraparameters_size_v2(msgcontent);
2380 : /* Ecu Id, App Id, Ctx Id and Session Id*/
2381 0 : msg.extendedheadersizev2 =
2382 0 : (uint32_t)(1 + strlen(DLT_DAEMON_ECU_ID) + 1 + strlen(app_id) + 1 + strlen(ctx_id) + sizeof(uint32_t));
2383 :
2384 0 : msg.headersizev2 = (int32_t)(msg.storageheadersizev2 + msg.baseheadersizev2 + msg.baseheaderextrasizev2
2385 0 : + msg.extendedheadersizev2);
2386 :
2387 0 : msg.headerbufferv2 = (uint8_t*)malloc((size_t)msg.headersizev2);
2388 :
2389 0 : if (dlt_set_storageheader_v2(&(msg.storageheaderv2), (uint8_t)strlen(DLT_DAEMON_ECU_ID), DLT_DAEMON_ECU_ID)
2390 : != DLT_RETURN_OK)
2391 : return DLT_RETURN_ERROR;
2392 :
2393 0 : if (dlt_message_set_storageparameters_v2(&msg, 0) != DLT_RETURN_OK)
2394 : return DLT_RETURN_ERROR;
2395 :
2396 : /* Set standardheader */
2397 0 : msg.baseheaderv2 = (DltBaseHeaderV2*)(msg.headerbufferv2 + msg.storageheadersizev2);
2398 : msg.baseheaderv2->htyp2 = DLT_HTYP2_PROTOCOL_VERSION2;
2399 : msg.baseheaderv2->htyp2 |= msgcontent;
2400 : msg.baseheaderv2->htyp2 |= DLT_HTYP2_WEID;
2401 : msg.baseheaderv2->htyp2 |= DLT_HTYP2_WACID;
2402 0 : msg.baseheaderv2->htyp2 |= DLT_HTYP2_WSID;
2403 :
2404 0 : msg.baseheaderv2->mcnt = uiMsgCount++;
2405 :
2406 : /* Fill base header conditional parameters */
2407 0 : msg.headerextrav2.msin = (uint8_t)(DLT_MSIN_VERB | (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT)
2408 0 : | ((level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN));
2409 0 : msg.headerextrav2.noar = 1; /* number of arguments */
2410 : memset(msg.headerextrav2.seconds, 0, 5);
2411 0 : msg.headerextrav2.nanoseconds = 0;
2412 :
2413 : #if defined(__WIN32__) || defined(_MSC_VER)
2414 : time_t t = time(NULL);
2415 : if (t == -1) {
2416 : uint32_t tcnt = (uint32_t)(GetTickCount()); /* GetTickCount() in 10 ms resolution */
2417 : tcnt_seconds = tcnt / 100;
2418 : tcnt_ns = (tcnt - (tcnt * 100)) * 10000;
2419 : msg.headerextrav2.seconds[0] = (tcnt_seconds >> 32) & 0xFF;
2420 : msg.headerextrav2.seconds[1] = (uint8_t)((tcnt_seconds >> 24) & 0xFF);
2421 : msg.headerextrav2.seconds[2] = (uint8_t)((tcnt_seconds >> 16) & 0xFF);
2422 : msg.headerextrav2.seconds[3] = (uint8_t)((tcnt_seconds >> 8) & 0xFF);
2423 : msg.headerextrav2.seconds[4] = (uint8_t)(tcnt_seconds & 0xFF);
2424 : if (ts.tv_nsec < 0x3B9ACA00) {
2425 : msg.headerextrav2.nanoseconds = tcnt_ns;
2426 : }
2427 : } else {
2428 : msg.headerextrav2.seconds[0] = (uint8_t)((t >> 32) & 0xFF);
2429 : msg.headerextrav2.seconds[1] = (uint8_t)((t >> 24) & 0xFF);
2430 : msg.headerextrav2.seconds[2] = (uint8_t)((t >> 16) & 0xFF);
2431 : msg.headerextrav2.seconds[3] = (uint8_t)((t >> 8) & 0xFF);
2432 : msg.headerextrav2.seconds[4] = (uint8_t)(t & 0xFF);
2433 : msg.headerextrav2.nanoseconds |= 0x80000000;
2434 : }
2435 : #else
2436 : struct timespec ts;
2437 0 : if (clock_gettime(CLOCK_REALTIME, &ts) == 0) {
2438 0 : msg.headerextrav2.seconds[0] = (uint8_t)(((uint64_t)ts.tv_sec >> 32) & 0xFF);
2439 0 : msg.headerextrav2.seconds[1] = (uint8_t)((ts.tv_sec >> 24) & 0xFF);
2440 0 : msg.headerextrav2.seconds[2] = (uint8_t)((ts.tv_sec >> 16) & 0xFF);
2441 0 : msg.headerextrav2.seconds[3] = (uint8_t)((ts.tv_sec >> 8) & 0xFF);
2442 0 : msg.headerextrav2.seconds[4] = (uint8_t)(ts.tv_sec & 0xFF);
2443 0 : if (ts.tv_nsec < 0x3B9ACA00) {
2444 0 : msg.headerextrav2.nanoseconds = (uint32_t)ts.tv_nsec; /* value is long */
2445 : }
2446 0 : } else if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
2447 0 : msg.headerextrav2.seconds[0] = (uint8_t)(((uint64_t)ts.tv_sec >> 32) & 0xFF);
2448 0 : msg.headerextrav2.seconds[1] = (uint8_t)((ts.tv_sec >> 24) & 0xFF);
2449 0 : msg.headerextrav2.seconds[2] = (uint8_t)((ts.tv_sec >> 16) & 0xFF);
2450 0 : msg.headerextrav2.seconds[3] = (uint8_t)((ts.tv_sec >> 8) & 0xFF);
2451 0 : msg.headerextrav2.seconds[4] = (uint8_t)(ts.tv_sec & 0xFF);
2452 0 : if (ts.tv_nsec < 0x3B9ACA00) {
2453 0 : msg.headerextrav2.nanoseconds = (uint32_t)ts.tv_nsec; /* value is long */
2454 : }
2455 0 : msg.headerextrav2.nanoseconds |= 0x80000000;
2456 : }
2457 : #endif
2458 :
2459 : /* Copy header extra parameters to headerbuffer */
2460 0 : if (dlt_message_set_extraparameters_v2(&msg, 0) == DLT_RETURN_ERROR) {
2461 0 : dlt_message_free_v2(&msg, 0);
2462 0 : return DLT_RETURN_ERROR;
2463 : }
2464 :
2465 : /* Fill out extended header */
2466 0 : if (DLT_IS_HTYP2_WEID(msg.baseheaderv2->htyp2)) {
2467 0 : msg.extendedheaderv2.ecidlen = (uint8_t)strlen(DLT_DAEMON_ECU_ID);
2468 : if (msg.extendedheaderv2.ecidlen > 0) {
2469 0 : dlt_set_id_v2(ecid_buf, DLT_DAEMON_ECU_ID, msg.extendedheaderv2.ecidlen);
2470 0 : msg.extendedheaderv2.ecid = ecid_buf;
2471 : } else {
2472 : msg.extendedheaderv2.ecid = NULL;
2473 : }
2474 : }
2475 :
2476 0 : if (DLT_IS_HTYP2_WACID(msg.baseheaderv2->htyp2)) {
2477 0 : msg.extendedheaderv2.apidlen = (uint8_t)strlen(app_id);
2478 0 : if (msg.extendedheaderv2.apidlen > 0) {
2479 0 : dlt_set_id_v2(apid_buf, app_id, msg.extendedheaderv2.apidlen);
2480 0 : msg.extendedheaderv2.apid = apid_buf;
2481 : } else {
2482 0 : msg.extendedheaderv2.apid = NULL;
2483 : }
2484 :
2485 0 : msg.extendedheaderv2.ctidlen = (uint8_t)strlen(ctx_id);
2486 0 : if (msg.extendedheaderv2.ctidlen > 0) {
2487 0 : dlt_set_id_v2(ctid_buf, ctx_id, msg.extendedheaderv2.ctidlen);
2488 0 : msg.extendedheaderv2.ctid = ctid_buf;
2489 : } else {
2490 0 : msg.extendedheaderv2.ctid = NULL;
2491 : }
2492 : }
2493 :
2494 0 : if (DLT_IS_HTYP2_WSID(msg.baseheaderv2->htyp2)) {
2495 0 : msg.extendedheaderv2.seid = (uint32_t)getpid();
2496 : }
2497 :
2498 0 : if (dlt_message_set_extendedparameters_v2(&msg) != DLT_RETURN_OK) {
2499 0 : dlt_message_free_v2(&msg, 0);
2500 0 : return DLT_RETURN_ERROR;
2501 : }
2502 :
2503 : /* Set payload data... */
2504 0 : uiType = DLT_TYPE_INFO_STRG;
2505 0 : uiSize = (uint16_t)(strlen(str) + 1);
2506 0 : msg.datasize = (int32_t)(sizeof(uint32_t) + sizeof(uint16_t) + uiSize);
2507 :
2508 0 : msg.databuffer = (uint8_t*)malloc((size_t)msg.datasize);
2509 0 : msg.databuffersize = msg.datasize;
2510 :
2511 0 : if (msg.databuffer == 0) {
2512 0 : dlt_log(LOG_WARNING, "Can't allocate buffer for get log info message\n");
2513 0 : return -1;
2514 : }
2515 :
2516 0 : msg.datasize = 0;
2517 : memcpy((uint8_t*)(msg.databuffer + msg.datasize), (uint8_t*)(&uiType), sizeof(uint32_t));
2518 0 : msg.datasize += (int32_t)sizeof(uint32_t);
2519 0 : memcpy((uint8_t*)(msg.databuffer + msg.datasize), (uint8_t*)(&uiSize), sizeof(uint16_t));
2520 0 : msg.datasize += (int32_t)sizeof(uint16_t);
2521 0 : memcpy((uint8_t*)(msg.databuffer + msg.datasize), str, uiSize);
2522 0 : msg.datasize += uiSize;
2523 :
2524 : /* Calc length */
2525 0 : msg.baseheaderv2->len =
2526 0 : DLT_HTOBE_16((uint16_t)(msg.headersizev2 - (int32_t)msg.storageheadersizev2 + msg.datasize));
2527 :
2528 0 : dlt_daemon_client_send_v2(
2529 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, msg.headerbufferv2, (int)msg.storageheadersizev2,
2530 0 : msg.headerbufferv2 + msg.storageheadersizev2, (int)(msg.headersizev2 - (int32_t)msg.storageheadersizev2),
2531 0 : msg.databuffer, (int)msg.datasize, verbose);
2532 :
2533 0 : dlt_message_free_v2(&msg, 0);
2534 4 : } else if (daemon->daemon_version == 1) {
2535 4 : DltMessage msg = {0};
2536 :
2537 : DltStandardHeaderExtra* pStandardExtra = NULL;
2538 : uint32_t uiType;
2539 : uint16_t uiSize;
2540 : uint32_t uiExtraSize;
2541 :
2542 4 : PRINT_FUNCTION_VERBOSE(verbose);
2543 :
2544 : /* Set storageheader */
2545 4 : msg.storageheader = (DltStorageHeader*)(msg.headerbuffer);
2546 4 : dlt_set_storageheader(msg.storageheader, daemon->ecuid);
2547 :
2548 : /* Set standardheader */
2549 4 : msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
2550 4 : msg.standardheader->htyp =
2551 : DLT_HTYP_UEH | DLT_HTYP_WEID | DLT_HTYP_WSID | DLT_HTYP_WTMS | DLT_HTYP_PROTOCOL_VERSION1;
2552 4 : msg.standardheader->mcnt = uiMsgCount++;
2553 :
2554 : uiExtraSize = (uint32_t)(DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)
2555 : + (DLT_IS_HTYP_UEH(msg.standardheader->htyp) ? sizeof(DltExtendedHeader) : 0));
2556 4 : msg.headersize =
2557 : (int32_t)((size_t)sizeof(DltStorageHeader) + (size_t)sizeof(DltStandardHeader) + (size_t)uiExtraSize);
2558 :
2559 : /* Set extraheader */
2560 : pStandardExtra =
2561 : (DltStandardHeaderExtra*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader));
2562 4 : dlt_set_id(pStandardExtra->ecu, daemon->ecuid);
2563 4 : pStandardExtra->tmsp = DLT_HTOBE_32(dlt_uptime());
2564 4 : pStandardExtra->seid = DLT_HTOBE_32((uint32_t)getpid());
2565 :
2566 : /* Set extendedheader */
2567 4 : msg.extendedheader =
2568 4 : (DltExtendedHeader*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader)
2569 4 : + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp));
2570 4 : msg.extendedheader->msin = (uint8_t)(DLT_MSIN_VERB | (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT)
2571 4 : | ((level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN));
2572 4 : msg.extendedheader->noar = 1;
2573 4 : dlt_set_id(msg.extendedheader->apid, app_id);
2574 4 : dlt_set_id(msg.extendedheader->ctid, ctx_id);
2575 :
2576 : /* Set payload data... */
2577 4 : uiType = DLT_TYPE_INFO_STRG;
2578 4 : uiSize = (uint16_t)(strlen(str) + 1);
2579 4 : msg.datasize = (int32_t)((size_t)sizeof(uint32_t) + (size_t)sizeof(uint16_t) + (size_t)uiSize);
2580 :
2581 4 : msg.databuffer = (uint8_t*)malloc((size_t)msg.datasize);
2582 4 : msg.databuffersize = (int32_t)msg.datasize;
2583 :
2584 4 : if (msg.databuffer == 0) {
2585 0 : dlt_log(LOG_WARNING, "Can't allocate buffer for get log info message\n");
2586 0 : return -1;
2587 : }
2588 :
2589 4 : msg.datasize = 0;
2590 : memcpy((uint8_t*)(msg.databuffer + msg.datasize), (uint8_t*)(&uiType), sizeof(uint32_t));
2591 4 : msg.datasize += (int32_t)sizeof(uint32_t);
2592 4 : memcpy((uint8_t*)(msg.databuffer + msg.datasize), (uint8_t*)(&uiSize), sizeof(uint16_t));
2593 4 : msg.datasize += (int32_t)sizeof(uint16_t);
2594 4 : memcpy((uint8_t*)(msg.databuffer + msg.datasize), str, uiSize);
2595 4 : msg.datasize += (int32_t)uiSize;
2596 :
2597 : /* Calc length */
2598 4 : msg.standardheader->len =
2599 4 : DLT_HTOBE_16((uint16_t)((size_t)msg.headersize - sizeof(DltStorageHeader) + (size_t)msg.datasize));
2600 :
2601 4 : dlt_daemon_client_send(
2602 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, msg.headerbuffer, sizeof(DltStorageHeader),
2603 : msg.headerbuffer + sizeof(DltStorageHeader), (int)(msg.headersize - (int32_t)sizeof(DltStorageHeader)),
2604 4 : msg.databuffer, (int)msg.datasize, verbose);
2605 :
2606 4 : free(msg.databuffer);
2607 : } else {
2608 : return -1;
2609 : }
2610 :
2611 : return 0;
2612 : }
2613 :
2614 0 : int dlt_daemon_check_numeric_setting(char* token, char* value, unsigned long* data)
2615 0 : {
2616 0 : char value_check[value_length];
2617 0 : value_check[0] = 0;
2618 0 : sscanf(value, "%lu%s", data, value_check);
2619 0 : if (value_check[0] || !isdigit(value[0])) {
2620 0 : fprintf(stderr, "Invalid input [%s] detected in option %s\n", value, token);
2621 0 : return -1;
2622 : }
2623 : return 0;
2624 : }
2625 :
2626 0 : int dlt_daemon_process_client_connect(
2627 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* receiver, int verbose)
2628 : {
2629 : socklen_t cli_size;
2630 : struct sockaddr_un cli;
2631 :
2632 : int in_sock = -1;
2633 0 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = {'\0'};
2634 :
2635 0 : PRINT_FUNCTION_VERBOSE(verbose);
2636 :
2637 0 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
2638 0 : dlt_log(
2639 : LOG_ERR,
2640 : "Invalid function parameters used for function "
2641 : "dlt_daemon_process_client_connect()\n");
2642 0 : return -1;
2643 : }
2644 :
2645 : /* event from TCP server socket, new connection */
2646 0 : cli_size = sizeof(cli);
2647 :
2648 0 : if ((in_sock = accept(receiver->fd, (struct sockaddr*)&cli, &cli_size)) < 0) {
2649 0 : if (errno == ECONNABORTED) // Caused by nmap -v -p 3490 -Pn <IP of dlt-daemon>
2650 : return 0;
2651 0 : dlt_vlog(LOG_ERR, "accept() for socket %d failed: %s\n", receiver->fd, strerror(errno));
2652 0 : return -1;
2653 : }
2654 :
2655 0 : if (daemon->daemon_version == 2) {
2656 : /* check if file file descriptor was already used, and make it invalid if it
2657 : * is reused. */
2658 : /* This prevents sending messages to wrong file descriptor */
2659 0 : dlt_daemon_applications_invalidate_fd_v2(daemon, daemon->ecuid, in_sock, verbose);
2660 0 : dlt_daemon_contexts_invalidate_fd_v2(daemon, daemon->ecuid, in_sock, verbose);
2661 :
2662 : /* Set socket timeout in reception */
2663 : struct timeval timeout_send;
2664 0 : timeout_send.tv_sec = daemon_local->timeoutOnSend;
2665 0 : timeout_send.tv_usec = 0;
2666 :
2667 0 : if (setsockopt(in_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout_send, sizeof(timeout_send)) < 0)
2668 0 : dlt_log(LOG_WARNING, "setsockopt failed\n");
2669 :
2670 0 : if (dlt_connection_create(
2671 : daemon_local, &daemon_local->pEvent, in_sock, POLLIN, DLT_CONNECTION_CLIENT_MSG_TCP)) {
2672 0 : dlt_log(LOG_ERR, "Failed to register new client. \n");
2673 0 : close(in_sock);
2674 0 : return -1;
2675 : }
2676 :
2677 : /* send connection info about connected */
2678 0 : dlt_daemon_control_message_connection_info_v2(
2679 : in_sock, daemon, daemon_local, DLT_CONNECTION_STATUS_CONNECTED, "", verbose);
2680 :
2681 : /* send ecu version string */
2682 0 : if (daemon_local->flags.sendECUSoftwareVersion > 0) {
2683 : if (daemon_local->flags.sendECUSoftwareVersion > 0)
2684 0 : dlt_daemon_control_get_software_version_v2(
2685 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon_local->flags.vflag);
2686 :
2687 0 : if (daemon_local->flags.sendTimezone > 0)
2688 0 : dlt_daemon_control_message_timezone_v2(
2689 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon_local->flags.vflag);
2690 : }
2691 :
2692 0 : snprintf(
2693 : local_str, DLT_DAEMON_TEXTBUFSIZE, "New client connection #%d established, Total Clients : %d", in_sock,
2694 : daemon_local->client_connections);
2695 :
2696 0 : dlt_daemon_log_internal(
2697 : daemon, daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
2698 : daemon_local->flags.vflag);
2699 0 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
2700 :
2701 0 : if (daemon_local->client_connections == 1) {
2702 0 : if (daemon_local->flags.vflag)
2703 0 : dlt_log(LOG_DEBUG, "Send ring-buffer to client\n");
2704 :
2705 0 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_BUFFER);
2706 0 : if (dlt_daemon_send_ringbuffer_to_client_v2(daemon, daemon_local, verbose) == -1) {
2707 0 : dlt_log(LOG_WARNING, "Can't send contents of ringbuffer to clients\n");
2708 0 : close(in_sock);
2709 : in_sock = -1;
2710 0 : return -1;
2711 : }
2712 :
2713 : /* send new log state to all applications */
2714 0 : daemon->connectionState = 1;
2715 :
2716 0 : dlt_daemon_user_send_all_log_state_v2(daemon, verbose);
2717 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
2718 : /* Reset number of received bytes from FIFO */
2719 : daemon->bytes_recv = 0;
2720 : #endif
2721 : }
2722 0 : } else if (daemon->daemon_version == 1) {
2723 : /* check if file file descriptor was already used, and make it invalid if it
2724 : * is reused. */
2725 : /* This prevents sending messages to wrong file descriptor */
2726 0 : dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
2727 0 : dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
2728 :
2729 : /* Set socket timeout in reception */
2730 : struct timeval timeout_send;
2731 0 : timeout_send.tv_sec = daemon_local->timeoutOnSend;
2732 0 : timeout_send.tv_usec = 0;
2733 :
2734 0 : if (setsockopt(in_sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout_send, sizeof(timeout_send)) < 0)
2735 0 : dlt_log(LOG_WARNING, "setsockopt failed\n");
2736 :
2737 0 : if (dlt_connection_create(
2738 : daemon_local, &daemon_local->pEvent, in_sock, POLLIN, DLT_CONNECTION_CLIENT_MSG_TCP)) {
2739 0 : dlt_log(LOG_ERR, "Failed to register new client. \n");
2740 0 : close(in_sock);
2741 0 : return -1;
2742 : }
2743 :
2744 : /* send connection info about connected */
2745 0 : dlt_daemon_control_message_connection_info(
2746 : in_sock, daemon, daemon_local, DLT_CONNECTION_STATUS_CONNECTED, "", verbose);
2747 :
2748 : /* send ecu version string */
2749 0 : if (daemon_local->flags.sendECUSoftwareVersion > 0) {
2750 : if (daemon_local->flags.sendECUSoftwareVersion > 0)
2751 0 : dlt_daemon_control_get_software_version(
2752 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon_local->flags.vflag);
2753 :
2754 0 : if (daemon_local->flags.sendTimezone > 0)
2755 0 : dlt_daemon_control_message_timezone(
2756 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon_local->flags.vflag);
2757 : }
2758 :
2759 0 : snprintf(
2760 : local_str, DLT_DAEMON_TEXTBUFSIZE, "New client connection #%d established, Total Clients : %d", in_sock,
2761 : daemon_local->client_connections);
2762 :
2763 0 : dlt_daemon_log_internal(
2764 : daemon, daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
2765 : daemon_local->flags.vflag);
2766 0 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
2767 :
2768 0 : if (daemon_local->client_connections == 1) {
2769 0 : if (daemon_local->flags.vflag)
2770 0 : dlt_log(LOG_DEBUG, "Send ring-buffer to client\n");
2771 :
2772 0 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_BUFFER);
2773 :
2774 0 : if (dlt_daemon_send_ringbuffer_to_client(daemon, daemon_local, verbose) == -1) {
2775 0 : dlt_log(LOG_WARNING, "Can't send contents of ringbuffer to clients\n");
2776 0 : close(in_sock);
2777 : in_sock = -1;
2778 0 : return -1;
2779 : }
2780 :
2781 : /* send new log state to all applications */
2782 0 : daemon->connectionState = 1;
2783 0 : dlt_daemon_user_send_all_log_state(daemon, verbose);
2784 :
2785 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
2786 : /* Reset number of received bytes from FIFO */
2787 : daemon->bytes_recv = 0;
2788 : #endif
2789 : }
2790 : } else {
2791 : return -1;
2792 : }
2793 : return 0;
2794 : }
2795 :
2796 : /**
2797 : * Create a sanitized copy of the message for control processing
2798 : * This breaks the taint chain by creating a new clean message structure
2799 : * Uses allow list validation for all path-containing messages
2800 : * @param tainted_msg The tainted message from receiver
2801 : * @param secure_msg The secure message to populate (output)
2802 : * @return 0 on success, -1 on validation failure
2803 : */
2804 1 : static int dlt_daemon_create_secure_message(DltMessage* tainted_msg, DltMessage* secure_msg)
2805 : {
2806 : uint32_t service_id;
2807 : DltServiceOfflineLogstorage* tainted_req;
2808 : DltServiceOfflineLogstorage* secure_req;
2809 : char secure_mount_point[DLT_MOUNT_PATH_MAX];
2810 : size_t i;
2811 :
2812 1 : if ((tainted_msg == NULL) || (secure_msg == NULL))
2813 : return -1;
2814 :
2815 : /* Initialize secure message with clean data */
2816 : memset(secure_msg, 0, sizeof(DltMessage));
2817 :
2818 : /* Copy safe, non-tainted fields from message structure */
2819 1 : secure_msg->headersize = tainted_msg->headersize;
2820 1 : secure_msg->datasize = tainted_msg->datasize;
2821 1 : secure_msg->found_serialheader = tainted_msg->found_serialheader;
2822 1 : secure_msg->resync_offset = tainted_msg->resync_offset;
2823 :
2824 : /* Copy header buffers (these don't contain user-controlled paths) */
2825 1 : if (tainted_msg->headersize > 0 && tainted_msg->headersize < (int32_t)sizeof(secure_msg->headerbuffer)) {
2826 39 : for (i = 0; i < (size_t)tainted_msg->headersize; i++) {
2827 38 : secure_msg->headerbuffer[i] = tainted_msg->headerbuffer[i];
2828 : }
2829 : }
2830 :
2831 : /* Set up header pointers */
2832 1 : secure_msg->storageheader = (DltStorageHeader*)(secure_msg->headerbuffer);
2833 1 : secure_msg->standardheader = (DltStandardHeader*)(secure_msg->headerbuffer + sizeof(DltStorageHeader));
2834 : if (DLT_IS_HTYP_UEH(secure_msg->standardheader->htyp)) {
2835 : secure_msg->extendedheader =
2836 : (DltExtendedHeader*)(secure_msg->headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader)
2837 : + DLT_STANDARD_HEADER_EXTRA_SIZE(secure_msg->standardheader->htyp));
2838 : }
2839 :
2840 : /* Point to the same databuffer initially */
2841 1 : secure_msg->databuffer = tainted_msg->databuffer;
2842 1 : secure_msg->databuffersize = tainted_msg->databuffersize;
2843 :
2844 1 : if (tainted_msg->databuffer == NULL || tainted_msg->datasize < (int32_t)sizeof(uint32_t))
2845 : return 0;
2846 :
2847 : /* Get service ID */
2848 1 : service_id = DLT_ENDIAN_GET_32(tainted_msg->standardheader->htyp, *((uint32_t*)(tainted_msg->databuffer)));
2849 :
2850 : /* Sanitize logstorage messages with path validation */
2851 1 : if (service_id == DLT_SERVICE_ID_OFFLINE_LOGSTORAGE) {
2852 : /* Cast to logstorage request structure */
2853 : tainted_req = (DltServiceOfflineLogstorage*)(tainted_msg->databuffer);
2854 : if (tainted_req == NULL)
2855 : return -1;
2856 :
2857 : /* Ensure null-termination */
2858 1 : tainted_req->mount_point[DLT_MOUNT_PATH_MAX - 1] = '\0';
2859 :
2860 : /* Get path length */
2861 1 : size_t path_len = strnlen(tainted_req->mount_point, DLT_MOUNT_PATH_MAX);
2862 :
2863 : /* Validate basic path requirements */
2864 1 : if (path_len == 0) {
2865 : /* Empty path only allowed for sync all caches operation */
2866 1 : if (tainted_req->connection_type != DLT_OFFLINE_LOGSTORAGE_SYNC_CACHES) {
2867 0 : dlt_vlog(LOG_WARNING, "Rejected logstorage message with empty path\n");
2868 0 : return -1;
2869 : }
2870 : } else {
2871 : /* Path must be absolute (start with /) */
2872 0 : if (tainted_req->mount_point[0] != '/') {
2873 0 : dlt_vlog(LOG_WARNING, "Rejected logstorage message with non-absolute path\n");
2874 0 : return -1;
2875 : }
2876 : }
2877 :
2878 : /* Now sanitize the databuffer */
2879 : secure_req = (DltServiceOfflineLogstorage*)(secure_msg->databuffer);
2880 :
2881 : /* Explicitly sanitize: copy path to secure local buffer using allow list */
2882 : memset(secure_mount_point, 0, sizeof(secure_mount_point));
2883 1 : for (i = 0; i < DLT_MOUNT_PATH_MAX - 1 && tainted_req->mount_point[i] != '\0'; i++) {
2884 : char c = tainted_req->mount_point[i];
2885 : /* Apply allow list - only safe characters allowed */
2886 0 : if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '/' || c == '-'
2887 : || c == '_' || c == '.') {
2888 0 : secure_mount_point[i] = c;
2889 : } else {
2890 0 : dlt_vlog(
2891 : LOG_WARNING, "Rejected logstorage message with invalid character in path at position %zu\n", i);
2892 0 : return -1;
2893 : }
2894 : }
2895 1 : secure_mount_point[DLT_MOUNT_PATH_MAX - 1] = '\0';
2896 :
2897 : /* Check for path traversal attempts (defense in depth) */
2898 1 : if (strstr(secure_mount_point, "..") != NULL) {
2899 0 : dlt_vlog(LOG_WARNING, "Rejected logstorage message with path traversal attempt\n");
2900 0 : return -1;
2901 : }
2902 :
2903 : /* Deny consecutive slashes */
2904 1 : if (strstr(secure_mount_point, "//") != NULL) {
2905 0 : dlt_vlog(LOG_WARNING, "Rejected logstorage message with consecutive slashes in path\n");
2906 0 : return -1;
2907 : }
2908 :
2909 : /* Copy secure data to the secure message's databuffer */
2910 1025 : for (i = 0; i < DLT_MOUNT_PATH_MAX; i++) {
2911 1024 : secure_req->mount_point[i] = secure_mount_point[i];
2912 : }
2913 : }
2914 :
2915 : return 0;
2916 : }
2917 :
2918 0 : int dlt_daemon_process_client_messages(
2919 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* receiver, int verbose)
2920 : {
2921 : int bytes_to_be_removed = 0;
2922 : int must_close_socket = -1;
2923 :
2924 0 : PRINT_FUNCTION_VERBOSE(verbose);
2925 :
2926 0 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
2927 0 : dlt_log(
2928 : LOG_ERR,
2929 : "Invalid function parameters used for function "
2930 : "dlt_daemon_process_client_messages()\n");
2931 0 : return -1;
2932 : }
2933 :
2934 0 : must_close_socket = dlt_receiver_receive(receiver);
2935 :
2936 0 : if (must_close_socket < 0) {
2937 0 : dlt_daemon_close_socket(receiver->fd, daemon, daemon_local, verbose);
2938 0 : return -1;
2939 : }
2940 :
2941 0 : if (daemon->daemon_version == DLTProtocolV2) {
2942 : /* Process all received messages */
2943 0 : while (dlt_message_read_v2(
2944 0 : &(daemon_local->msgv2), (uint8_t*)receiver->buf, (unsigned int)receiver->bytesRcvd,
2945 : daemon_local->flags.nflag, daemon_local->flags.vflag)
2946 0 : == DLT_MESSAGE_ERROR_OK) {
2947 : /* Check for control message */
2948 0 : if ((0 < receiver->fd) && DLT_MSG_IS_CONTROL_REQUEST_V2(&(daemon_local->msgv2)))
2949 0 : dlt_daemon_client_process_control_v2(
2950 : receiver->fd, daemon, daemon_local, &(daemon_local->msgv2), daemon_local->flags.vflag);
2951 0 : bytes_to_be_removed = (int)(daemon_local->msgv2.headersizev2 + daemon_local->msgv2.datasize
2952 0 : - (int32_t)daemon_local->msgv2.storageheadersizev2);
2953 :
2954 0 : if (daemon_local->msg.found_serialheader)
2955 0 : bytes_to_be_removed += (int)sizeof(dltSerialHeader);
2956 :
2957 0 : if (daemon_local->msg.resync_offset)
2958 0 : bytes_to_be_removed += daemon_local->msg.resync_offset;
2959 :
2960 0 : if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) {
2961 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver for sockets\n");
2962 0 : return -1;
2963 : }
2964 : } /* while */
2965 0 : } else if (daemon->daemon_version == DLTProtocolV1) {
2966 : /* Process all received messages */
2967 0 : while (dlt_message_read(
2968 0 : &(daemon_local->msg), (uint8_t*)receiver->buf, (unsigned int)receiver->bytesRcvd,
2969 : daemon_local->flags.nflag, daemon_local->flags.vflag)
2970 0 : == DLT_MESSAGE_ERROR_OK) {
2971 : /* Check for control message */
2972 0 : if ((0 < receiver->fd) && DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg)))
2973 0 : dlt_daemon_client_process_control(
2974 : receiver->fd, daemon, daemon_local, &(daemon_local->msg), daemon_local->flags.vflag);
2975 :
2976 0 : bytes_to_be_removed = (int)((size_t)daemon_local->msg.headersize + (size_t)daemon_local->msg.datasize
2977 0 : - (size_t)sizeof(DltStorageHeader));
2978 :
2979 0 : if (daemon_local->msg.found_serialheader)
2980 : bytes_to_be_removed += (int)sizeof(dltSerialHeader);
2981 :
2982 0 : if (daemon_local->msg.resync_offset)
2983 0 : bytes_to_be_removed += daemon_local->msg.resync_offset;
2984 :
2985 0 : if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) {
2986 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver for sockets\n");
2987 0 : return -1;
2988 : }
2989 : } /* while */
2990 : } else {
2991 0 : dlt_vlog(LOG_ERR, "Unsupported DLT version %u in %s\n", daemon->daemon_version, __func__);
2992 0 : return -1;
2993 : }
2994 :
2995 0 : if (dlt_receiver_move_to_begin(receiver) == -1) {
2996 0 : dlt_log(LOG_WARNING, "Can't move bytes to beginning of receiver buffer for sockets\n");
2997 0 : return -1;
2998 : }
2999 :
3000 0 : if (must_close_socket == 0)
3001 : /* FIXME: Why the hell do we need to close the socket
3002 : * on control message reception ??
3003 : */
3004 0 : dlt_daemon_close_socket(receiver->fd, daemon, daemon_local, verbose);
3005 :
3006 : return 0;
3007 : }
3008 :
3009 0 : int dlt_daemon_process_client_messages_serial(
3010 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* receiver, int verbose)
3011 : {
3012 : int bytes_to_be_removed = 0;
3013 :
3014 0 : PRINT_FUNCTION_VERBOSE(verbose);
3015 :
3016 0 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
3017 0 : dlt_log(
3018 : LOG_ERR,
3019 : "Invalid function parameters used for function "
3020 : "dlt_daemon_process_client_messages_serial()\n");
3021 0 : return -1;
3022 : }
3023 :
3024 0 : if (dlt_receiver_receive(receiver) <= 0) {
3025 0 : dlt_log(
3026 : LOG_WARNING,
3027 : "dlt_receiver_receive_fd() for messages from serial interface "
3028 : "failed!\n");
3029 0 : return -1;
3030 : }
3031 :
3032 : /* Process all received messages */
3033 0 : while (dlt_message_read(
3034 0 : &(daemon_local->msg), (uint8_t*)receiver->buf, (unsigned int)receiver->bytesRcvd,
3035 : daemon_local->flags.mflag, daemon_local->flags.vflag)
3036 0 : == DLT_MESSAGE_ERROR_OK) {
3037 : /* Check for control message */
3038 0 : if (DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg))) {
3039 0 : DltMessage secure_msg = {0};
3040 : /* Create sanitized message to break taint chain */
3041 0 : if (dlt_daemon_create_secure_message(&(daemon_local->msg), &secure_msg) < 0)
3042 0 : continue;
3043 :
3044 0 : if (dlt_daemon_client_process_control(
3045 : receiver->fd, daemon, daemon_local, &(daemon_local->msg), daemon_local->flags.vflag)
3046 : == -1) {
3047 0 : dlt_log(LOG_WARNING, "Can't process control messages\n");
3048 0 : return -1;
3049 : }
3050 : }
3051 :
3052 : bytes_to_be_removed =
3053 0 : (int)((size_t)daemon_local->msg.headersize + (size_t)daemon_local->msg.datasize - sizeof(DltStorageHeader));
3054 :
3055 0 : if (daemon_local->msg.found_serialheader)
3056 : bytes_to_be_removed += (int)sizeof(dltSerialHeader);
3057 :
3058 0 : if (daemon_local->msg.resync_offset)
3059 0 : bytes_to_be_removed += daemon_local->msg.resync_offset;
3060 :
3061 0 : if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) {
3062 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver for serial connection\n");
3063 0 : return -1;
3064 : }
3065 : } /* while */
3066 :
3067 0 : if (dlt_receiver_move_to_begin(receiver) == -1) {
3068 0 : dlt_log(
3069 : LOG_WARNING,
3070 : "Can't move bytes to beginning of receiver buffer for serial "
3071 : "connection\n");
3072 0 : return -1;
3073 : }
3074 :
3075 : return 0;
3076 : }
3077 :
3078 1 : int dlt_daemon_process_control_connect(
3079 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* receiver, int verbose)
3080 : {
3081 : socklen_t ctrl_size;
3082 : struct sockaddr_un ctrl;
3083 : int in_sock = -1;
3084 :
3085 1 : PRINT_FUNCTION_VERBOSE(verbose);
3086 :
3087 1 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
3088 0 : dlt_log(
3089 : LOG_ERR,
3090 : "Invalid function parameters used for function "
3091 : "dlt_daemon_process_control_connect()\n");
3092 0 : return -1;
3093 : }
3094 :
3095 : /* event from UNIX server socket, new connection */
3096 1 : ctrl_size = sizeof(ctrl);
3097 :
3098 1 : if ((in_sock = accept(receiver->fd, (struct sockaddr*)&ctrl, &ctrl_size)) < 0) {
3099 0 : dlt_vlog(LOG_ERR, "accept() on UNIX control socket %d failed: %s\n", receiver->fd, strerror(errno));
3100 0 : return -1;
3101 : }
3102 :
3103 : /* check if file file descriptor was already used, and make it invalid if it
3104 : * is reused */
3105 : /* This prevents sending messages to wrong file descriptor */
3106 1 : if (daemon->daemon_version == 2) {
3107 0 : dlt_daemon_applications_invalidate_fd_v2(daemon, daemon->ecuid, in_sock, verbose);
3108 0 : dlt_daemon_contexts_invalidate_fd_v2(daemon, daemon->ecuid, in_sock, verbose);
3109 1 : } else if (daemon->daemon_version == 1) {
3110 1 : dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
3111 1 : dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
3112 : } else {
3113 : return -1;
3114 : }
3115 1 : dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
3116 1 : dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
3117 :
3118 1 : if (dlt_connection_create(daemon_local, &daemon_local->pEvent, in_sock, POLLIN, DLT_CONNECTION_CONTROL_MSG)) {
3119 0 : dlt_log(LOG_ERR, "Failed to register new client. \n");
3120 : /* TODO: Perform clean-up */
3121 0 : return -1;
3122 : }
3123 :
3124 1 : if (verbose)
3125 0 : dlt_vlog(LOG_INFO, "New connection to control client established\n");
3126 :
3127 : return 0;
3128 : }
3129 :
3130 : #if defined DLT_DAEMON_USE_UNIX_SOCKET_IPC || defined DLT_DAEMON_VSOCK_IPC_ENABLE
3131 : int dlt_daemon_process_app_connect(DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* receiver, int verbose)
3132 : {
3133 : int in_sock = -1;
3134 :
3135 : PRINT_FUNCTION_VERBOSE(verbose);
3136 :
3137 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
3138 : dlt_vlog(LOG_ERR, "%s: Invalid parameters\n", __func__);
3139 : return DLT_RETURN_WRONG_PARAMETER;
3140 : }
3141 :
3142 : /* event from server socket, new connection */
3143 :
3144 : if ((in_sock = accept(receiver->fd, NULL, NULL)) < 0) {
3145 : dlt_vlog(LOG_ERR, "accept() on UNIX socket %d failed: %s\n", receiver->fd, strerror(errno));
3146 : return -1;
3147 : }
3148 :
3149 : /* check if file file descriptor was already used, and make it invalid if it
3150 : * is reused. This prevents sending messages to wrong file descriptor */
3151 : dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
3152 : dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
3153 :
3154 : if (dlt_connection_create(daemon_local, &daemon_local->pEvent, in_sock, POLLIN, DLT_CONNECTION_APP_MSG)) {
3155 : dlt_log(LOG_ERR, "Failed to register new application. \n");
3156 : close(in_sock);
3157 : return -1;
3158 : }
3159 :
3160 : if (verbose)
3161 : dlt_vlog(LOG_INFO, "New connection to application established\n");
3162 :
3163 : return 0;
3164 : }
3165 : #endif
3166 :
3167 2 : int dlt_daemon_process_control_messages(
3168 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* receiver, int verbose)
3169 : {
3170 : int bytes_to_be_removed = 0;
3171 :
3172 2 : PRINT_FUNCTION_VERBOSE(verbose);
3173 :
3174 2 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
3175 0 : dlt_log(
3176 : LOG_ERR,
3177 : "Invalid function parameters used for function "
3178 : "dlt_daemon_process_control_messages()\n");
3179 0 : return -1;
3180 : }
3181 :
3182 2 : if (dlt_receiver_receive(receiver) <= 0) {
3183 1 : dlt_daemon_close_socket(receiver->fd, daemon, daemon_local, verbose);
3184 1 : return -1;
3185 : }
3186 :
3187 1 : if (daemon->daemon_version == DLTProtocolV2) {
3188 : /* Process all received messages */
3189 0 : while (dlt_message_read_v2(
3190 0 : &(daemon_local->msgv2), (uint8_t*)receiver->buf, (unsigned int)receiver->bytesRcvd,
3191 : daemon_local->flags.nflag, daemon_local->flags.vflag)
3192 0 : == DLT_MESSAGE_ERROR_OK) {
3193 : /* Check for control message */
3194 0 : if ((0 < receiver->fd) && DLT_MSG_IS_CONTROL_REQUEST_V2(&(daemon_local->msgv2)))
3195 0 : dlt_daemon_client_process_control_v2(
3196 : receiver->fd, daemon, daemon_local, &(daemon_local->msgv2), daemon_local->flags.vflag);
3197 0 : bytes_to_be_removed = (int)(daemon_local->msgv2.headersizev2 + daemon_local->msgv2.datasize
3198 0 : - (int32_t)daemon_local->msgv2.storageheadersizev2);
3199 :
3200 0 : if (daemon_local->msg.found_serialheader)
3201 0 : bytes_to_be_removed += (int)sizeof(dltSerialHeader);
3202 :
3203 0 : if (daemon_local->msg.resync_offset)
3204 0 : bytes_to_be_removed += daemon_local->msg.resync_offset;
3205 :
3206 0 : if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) {
3207 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver for sockets\n");
3208 0 : return -1;
3209 : }
3210 : } /* while */
3211 1 : } else if (daemon->daemon_version == DLTProtocolV1) {
3212 : /* Process all received messages */
3213 2 : while (dlt_message_read(
3214 2 : &(daemon_local->msg), (uint8_t*)receiver->buf, (unsigned int)receiver->bytesRcvd,
3215 : daemon_local->flags.nflag, daemon_local->flags.vflag)
3216 2 : == DLT_MESSAGE_ERROR_OK) {
3217 : /* Check for control message */
3218 1 : if ((receiver->fd > 0) && DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg))) {
3219 1 : DltMessage secure_msg = {0};
3220 : /* Create sanitized message to break taint chain */
3221 1 : if (dlt_daemon_create_secure_message(&(daemon_local->msg), &secure_msg) < 0)
3222 0 : continue;
3223 :
3224 1 : if (dlt_daemon_client_process_control(
3225 : receiver->fd, daemon, daemon_local, &secure_msg, daemon_local->flags.vflag)
3226 : == -1) {
3227 0 : dlt_log(LOG_WARNING, "Can't process control messages\n");
3228 0 : return -1;
3229 : }
3230 : }
3231 :
3232 1 : bytes_to_be_removed = (int)((size_t)daemon_local->msg.headersize + (size_t)daemon_local->msg.datasize
3233 1 : - sizeof(DltStorageHeader));
3234 :
3235 1 : if (daemon_local->msg.found_serialheader)
3236 : bytes_to_be_removed += (int)sizeof(dltSerialHeader);
3237 :
3238 1 : if (daemon_local->msg.resync_offset)
3239 0 : bytes_to_be_removed += daemon_local->msg.resync_offset;
3240 :
3241 1 : if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) {
3242 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver for sockets\n");
3243 0 : return -1;
3244 : }
3245 : } /* while */
3246 : } else {
3247 0 : dlt_vlog(LOG_ERR, "Unsupported DLT version %u in %s\n", daemon->daemon_version, __func__);
3248 0 : return -1;
3249 : }
3250 :
3251 1 : if (dlt_receiver_move_to_begin(receiver) == -1) {
3252 0 : dlt_log(LOG_WARNING, "Can't move bytes to beginning of receiver buffer for sockets\n");
3253 0 : return -1;
3254 : }
3255 :
3256 : return 0;
3257 : }
3258 :
3259 0 : static int dlt_daemon_process_user_message_not_sup(
3260 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* receiver, int verbose)
3261 : {
3262 0 : DltUserHeader* userheader = (DltUserHeader*)(receiver->buf);
3263 : (void)daemon;
3264 : (void)daemon_local;
3265 :
3266 0 : PRINT_FUNCTION_VERBOSE(verbose);
3267 :
3268 0 : dlt_vlog(LOG_ERR, "Invalid user message type received: %u!\n", userheader->message);
3269 :
3270 : /* remove user header */
3271 0 : if (dlt_receiver_remove(receiver, sizeof(DltUserHeader)) == -1)
3272 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver for user messages\n");
3273 :
3274 0 : return -1;
3275 : }
3276 :
3277 : static dlt_daemon_process_user_message_func process_user_func[DLT_USER_MESSAGE_NOT_SUPPORTED] = {
3278 : dlt_daemon_process_user_message_not_sup,
3279 : dlt_daemon_process_user_message_log,
3280 : dlt_daemon_process_user_message_register_application,
3281 : dlt_daemon_process_user_message_unregister_application,
3282 : dlt_daemon_process_user_message_register_context,
3283 : dlt_daemon_process_user_message_unregister_context,
3284 : dlt_daemon_process_user_message_not_sup,
3285 : dlt_daemon_process_user_message_not_sup,
3286 : dlt_daemon_process_user_message_overflow,
3287 : dlt_daemon_process_user_message_set_app_ll_ts,
3288 : dlt_daemon_process_user_message_not_sup,
3289 : dlt_daemon_process_user_message_not_sup,
3290 : dlt_daemon_process_user_message_not_sup,
3291 : dlt_daemon_process_user_message_marker,
3292 : dlt_daemon_process_user_message_not_sup,
3293 : dlt_daemon_process_user_message_not_sup};
3294 :
3295 269 : int dlt_daemon_process_user_messages(
3296 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* receiver, int verbose)
3297 : {
3298 : int offset = 0;
3299 : int run_loop = 1;
3300 : int32_t min_size = (int32_t)sizeof(DltUserHeader);
3301 : DltUserHeader* userheader;
3302 : int recv;
3303 :
3304 269 : PRINT_FUNCTION_VERBOSE(verbose);
3305 :
3306 269 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
3307 0 : dlt_log(
3308 : LOG_ERR,
3309 : "Invalid function parameters used for function "
3310 : "dlt_daemon_process_user_messages()\n");
3311 0 : return -1;
3312 : }
3313 :
3314 269 : recv = dlt_receiver_receive(receiver);
3315 :
3316 269 : if (recv <= 0 && receiver->type == DLT_RECEIVE_SOCKET) {
3317 0 : dlt_daemon_close_socket(receiver->fd, daemon, daemon_local, verbose);
3318 0 : return 0;
3319 0 : } else if (recv < 0) {
3320 0 : dlt_log(LOG_WARNING, "dlt_receiver_receive_fd() for user messages failed!\n");
3321 0 : return -1;
3322 : }
3323 :
3324 :
3325 269 : if (daemon->daemon_version == DLTProtocolV2) {
3326 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
3327 : /* Count up number of received bytes from FIFO */
3328 : if (receiver->bytesRcvd > receiver->lastBytesRcvd) {
3329 : daemon->bytes_recv += receiver->bytesRcvd - receiver->lastBytesRcvd;
3330 : }
3331 : #endif
3332 :
3333 : /* look through buffer as long as data is in there */
3334 0 : while ((receiver->bytesRcvd >= min_size) && run_loop) {
3335 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
3336 : /* this loop may be running long, so we have to exit it at some point to be able to
3337 : * to process other events, like feeding the watchdog
3338 : */
3339 : bool watchdog_triggered = dlt_daemon_trigger_systemd_watchdog_if_necessary(daemon);
3340 : if (watchdog_triggered) {
3341 : dlt_vlog(LOG_WARNING, "%s yields due to watchdog.\n", __func__);
3342 : run_loop = 0; // exit loop in next iteration
3343 : }
3344 : #endif
3345 : dlt_daemon_process_user_message_func func = NULL;
3346 :
3347 : offset = 0;
3348 0 : userheader = (DltUserHeader*)(receiver->buf + offset);
3349 :
3350 0 : while (!dlt_user_check_userheader(userheader) && (offset + min_size <= receiver->bytesRcvd)) {
3351 : /* resync if necessary */
3352 0 : offset++;
3353 0 : userheader = (DltUserHeader*)(receiver->buf + offset);
3354 : }
3355 :
3356 : /* Check for user header pattern */
3357 0 : if (!dlt_user_check_userheader(userheader))
3358 : break;
3359 :
3360 : /* Set new start offset */
3361 0 : if (offset > 0) {
3362 0 : if (dlt_receiver_remove(receiver, offset) == -1) {
3363 0 : dlt_log(LOG_WARNING, "Can't remove offset from receiver\n");
3364 0 : return -1;
3365 : }
3366 : }
3367 0 : if (userheader->message >= DLT_USER_MESSAGE_NOT_SUPPORTED)
3368 : func = dlt_daemon_process_user_message_not_sup;
3369 : else
3370 0 : func = process_user_func[userheader->message];
3371 :
3372 0 : if (func(daemon, daemon_local, receiver, daemon_local->flags.vflag) == -1)
3373 : run_loop = 0;
3374 : }
3375 :
3376 : /* keep not read data in buffer */
3377 0 : if (dlt_receiver_move_to_begin(receiver) == -1) {
3378 0 : dlt_log(
3379 : LOG_WARNING,
3380 : "Can't move bytes to beginning of receiver buffer for user "
3381 : "messages\n");
3382 0 : return -1;
3383 : }
3384 269 : } else if (daemon->daemon_version == DLTProtocolV1) {
3385 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
3386 : /* Count up number of received bytes from FIFO */
3387 : if (receiver->bytesRcvd > receiver->lastBytesRcvd) {
3388 : daemon->bytes_recv += receiver->bytesRcvd - receiver->lastBytesRcvd;
3389 : }
3390 : #endif
3391 :
3392 : /* look through buffer as long as data is in there */
3393 713 : while ((receiver->bytesRcvd >= min_size) && run_loop) {
3394 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
3395 : /* this loop may be running long, so we have to exit it at some point to be able to
3396 : * to process other events, like feeding the watchdog
3397 : */
3398 : bool watchdog_triggered = dlt_daemon_trigger_systemd_watchdog_if_necessary(daemon);
3399 : if (watchdog_triggered) {
3400 : dlt_vlog(LOG_WARNING, "%s yields due to watchdog.\n", __func__);
3401 : run_loop = 0; // exit loop in next iteration
3402 : }
3403 : #endif
3404 : dlt_daemon_process_user_message_func func = NULL;
3405 :
3406 : offset = 0;
3407 444 : userheader = (DltUserHeader*)(receiver->buf + offset);
3408 :
3409 444 : while (!dlt_user_check_userheader(userheader) && (offset + min_size <= receiver->bytesRcvd)) {
3410 : /* resync if necessary */
3411 0 : offset++;
3412 0 : userheader = (DltUserHeader*)(receiver->buf + offset);
3413 : }
3414 :
3415 : /* Check for user header pattern */
3416 444 : if (!dlt_user_check_userheader(userheader))
3417 : break;
3418 :
3419 : /* Set new start offset */
3420 444 : if (offset > 0) {
3421 0 : if (dlt_receiver_remove(receiver, offset) == -1) {
3422 0 : dlt_log(LOG_WARNING, "Can't remove offset from receiver\n");
3423 0 : return -1;
3424 : }
3425 : }
3426 :
3427 444 : if (userheader->message >= DLT_USER_MESSAGE_NOT_SUPPORTED)
3428 : func = dlt_daemon_process_user_message_not_sup;
3429 : else
3430 444 : func = process_user_func[userheader->message];
3431 :
3432 444 : if (func(daemon, daemon_local, receiver, daemon_local->flags.vflag) == -1)
3433 : run_loop = 0;
3434 : }
3435 :
3436 : /* keep not read data in buffer */
3437 269 : if (dlt_receiver_move_to_begin(receiver) == -1) {
3438 0 : dlt_log(
3439 : LOG_WARNING,
3440 : "Can't move bytes to beginning of receiver buffer for user "
3441 : "messages\n");
3442 0 : return -1;
3443 : }
3444 : } else {
3445 0 : dlt_vlog(LOG_ERR, "Unsupported DLT version %u in %s\n", daemon->daemon_version, __func__);
3446 0 : return -1;
3447 : }
3448 :
3449 : return 0;
3450 : }
3451 :
3452 0 : int dlt_daemon_process_user_message_overflow(
3453 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* rec, int verbose)
3454 : {
3455 : uint32_t len = sizeof(DltUserControlMsgBufferOverflow);
3456 : DltUserControlMsgBufferOverflow userpayload;
3457 :
3458 0 : PRINT_FUNCTION_VERBOSE(verbose);
3459 :
3460 0 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
3461 0 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__);
3462 0 : return -1;
3463 : }
3464 :
3465 0 : if (dlt_receiver_check_and_get(rec, &userpayload, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
3466 : /* Not enough bytes received */
3467 : return -1;
3468 :
3469 : /* Store in daemon, that a message buffer overflow has occured */
3470 : /* look if TCP connection to client is available or it least message can be put into buffer */
3471 0 : if (dlt_daemon_control_message_buffer_overflow(
3472 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, userpayload.overflow_counter, userpayload.apid, verbose))
3473 : /* there was an error when storing message */
3474 : /* add the counter of lost messages to the daemon counter */
3475 0 : daemon->overflow_counter += userpayload.overflow_counter;
3476 :
3477 : return 0;
3478 : }
3479 :
3480 0 : int dlt_daemon_send_message_overflow(DltDaemon* daemon, DltDaemonLocal* daemon_local, int verbose)
3481 : {
3482 : int ret;
3483 0 : PRINT_FUNCTION_VERBOSE(verbose);
3484 :
3485 0 : if ((daemon == 0) || (daemon_local == 0)) {
3486 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_overflow()\n");
3487 0 : return DLT_DAEMON_ERROR_UNKNOWN;
3488 : }
3489 :
3490 : /* Store in daemon, that a message buffer overflow has occured */
3491 0 : if ((ret = dlt_daemon_control_message_buffer_overflow(
3492 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon->overflow_counter, "", verbose)))
3493 : return ret;
3494 :
3495 : return DLT_DAEMON_ERROR_OK;
3496 : }
3497 :
3498 0 : int dlt_daemon_send_message_overflow_v2(DltDaemon* daemon, DltDaemonLocal* daemon_local, int verbose)
3499 : {
3500 : int ret;
3501 0 : PRINT_FUNCTION_VERBOSE(verbose);
3502 :
3503 0 : if ((daemon == 0) || (daemon_local == 0)) {
3504 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_overflow()\n");
3505 0 : return DLT_DAEMON_ERROR_UNKNOWN;
3506 : }
3507 :
3508 : /* Store in daemon, that a message buffer overflow has occured */
3509 0 : if ((ret = dlt_daemon_control_message_buffer_overflow_v2(
3510 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, daemon->overflow_counter, NULL, verbose)))
3511 : return ret;
3512 :
3513 : return DLT_DAEMON_ERROR_OK;
3514 : }
3515 :
3516 1 : int dlt_daemon_process_user_message_register_application(
3517 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* rec, int verbose)
3518 : {
3519 : uint32_t to_remove = 0;
3520 : DltDaemonApplication* application = NULL;
3521 1 : DltDaemonApplication* old_application = NULL;
3522 : pid_t old_pid = 0;
3523 1 : char description[DLT_DAEMON_DESCSIZE + 1] = {'\0'};
3524 : char* origin;
3525 : int fd = -1;
3526 :
3527 1 : PRINT_FUNCTION_VERBOSE(verbose);
3528 :
3529 1 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
3530 0 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__);
3531 0 : return -1;
3532 : }
3533 :
3534 1 : if (daemon->daemon_version == DLTProtocolV2) {
3535 : uint32_t len = sizeof(DltUserControlMsgRegisterApplicationV2);
3536 : DltUserControlMsgRegisterApplicationV2 usercontext;
3537 : memset(&usercontext, 0, sizeof(DltUserControlMsgRegisterApplicationV2));
3538 : usercontext.apid = NULL;
3539 : int usercontextSize;
3540 : uint8_t* buffer;
3541 :
3542 : int offset = 0;
3543 :
3544 0 : usercontext.apidlen = (uint8_t)rec->buf[8]; // TBD: write function to get apidlen from received buffer
3545 0 : usercontextSize = (int)(sizeof(uint8_t) + usercontext.apidlen + sizeof(pid_t) + sizeof(uint32_t));
3546 :
3547 0 : buffer = (uint8_t*)calloc((size_t)usercontextSize, 1);
3548 :
3549 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
3550 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__);
3551 0 : return -1;
3552 : }
3553 :
3554 : origin = rec->buf;
3555 :
3556 : /* Adding temp variable to check the return value */
3557 : int temp = 0;
3558 :
3559 : /* We shall not remove data before checking that everything is there. */
3560 0 : temp = dlt_receiver_check_and_get(rec, buffer, (unsigned int)usercontextSize, DLT_RCV_SKIP_HEADER);
3561 :
3562 0 : if (temp < 0) {
3563 : /* Not enough bytes received */
3564 : return -1;
3565 : } else {
3566 0 : to_remove = (uint32_t)temp;
3567 : }
3568 :
3569 : offset = 0;
3570 : memcpy(&usercontext.apidlen, buffer, 1);
3571 : offset += 1;
3572 0 : char apid_buf[DLT_V2_ID_SIZE + 1] = {0};
3573 0 : memcpy(apid_buf, (buffer + offset), usercontext.apidlen);
3574 0 : apid_buf[usercontext.apidlen] = '\0';
3575 0 : usercontext.apid = apid_buf;
3576 0 : offset += usercontext.apidlen;
3577 0 : memcpy(&(usercontext.pid), (buffer + offset), sizeof(pid_t));
3578 0 : offset += (int)sizeof(pid_t);
3579 0 : memcpy(&(usercontext.description_length), (buffer + offset), 4);
3580 : offset = 0;
3581 :
3582 : len = usercontext.description_length;
3583 :
3584 0 : if (len > DLT_DAEMON_DESCSIZE) {
3585 : len = DLT_DAEMON_DESCSIZE;
3586 0 : dlt_log(LOG_WARNING, "Application description exceeds limit\n");
3587 : }
3588 :
3589 : /* adjust buffer pointer */
3590 0 : rec->buf += to_remove + sizeof(DltUserHeader);
3591 :
3592 0 : if (dlt_receiver_check_and_get(rec, description, len, DLT_RCV_NONE) < 0) {
3593 0 : dlt_log(LOG_ERR, "Unable to get application description\n");
3594 : /* in case description was not readable, set dummy description */
3595 : memcpy(description, "Unknown", sizeof("Unknown"));
3596 : /* unknown len of original description, set to 0 to not remove in next step. Because message buffer is
3597 : * re-adjusted the corrupted description is ignored. */
3598 : len = 0;
3599 : }
3600 :
3601 : /* adjust to_remove */
3602 0 : to_remove += (uint32_t)sizeof(DltUserHeader) + len;
3603 :
3604 : /* point to begin of message */
3605 0 : rec->buf = origin;
3606 :
3607 : // TBD: Need init_v2 ?
3608 :
3609 : /* We can now remove data. */
3610 0 : if (dlt_receiver_remove(rec, (int)to_remove) != DLT_RETURN_OK) {
3611 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n");
3612 0 : return -1;
3613 : }
3614 :
3615 0 : dlt_daemon_application_find_v2(
3616 0 : daemon, usercontext.apidlen, usercontext.apid, daemon->ecuid2len, daemon->ecuid2, verbose,
3617 : &old_application);
3618 :
3619 0 : if (old_application != NULL)
3620 0 : old_pid = old_application->pid;
3621 :
3622 0 : if (rec->type == DLT_RECEIVE_SOCKET)
3623 0 : fd = rec->fd; /* For sockets, an app specific fd has already been created with accept(). */
3624 :
3625 0 : application = dlt_daemon_application_add_v2(
3626 0 : daemon, usercontext.apidlen, usercontext.apid, usercontext.pid, description, fd, daemon->ecuid2len,
3627 : daemon->ecuid2, verbose);
3628 :
3629 :
3630 : /* send log state to new application */
3631 0 : dlt_daemon_user_send_log_state_v2(daemon, application, verbose);
3632 :
3633 0 : if (application == NULL) {
3634 0 : dlt_vlog(LOG_WARNING, "Can't add ApplicationID '%s' for PID %d\n", usercontext.apid, usercontext.pid);
3635 0 : return -1;
3636 0 : } else if (old_pid != application->pid) {
3637 0 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = {'\0'};
3638 :
3639 0 : snprintf(
3640 : local_str, DLT_DAEMON_TEXTBUFSIZE, "ApplicationID '%s' registered for PID %d, Description=%s",
3641 0 : application->apid2, application->pid, application->application_description);
3642 :
3643 0 : dlt_daemon_log_internal(
3644 : daemon, daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
3645 : daemon_local->flags.vflag);
3646 0 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
3647 : }
3648 :
3649 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
3650 : if (dlt_daemon_user_send_trace_load_config(daemon, application, verbose) != DLT_RETURN_OK)
3651 : dlt_vlog(
3652 : LOG_WARNING, "Cannot send trace config to Apid: %.4s, PID: %d\n", application->apid, application->pid);
3653 : #endif
3654 0 : free(buffer);
3655 1 : } else if (daemon->daemon_version == DLTProtocolV1) {
3656 : DltUserControlMsgRegisterApplication userapp;
3657 : uint32_t len = sizeof(DltUserControlMsgRegisterApplication);
3658 : memset(&userapp, 0, sizeof(DltUserControlMsgRegisterApplication));
3659 1 : origin = rec->buf;
3660 :
3661 : /* Adding temp variable to check the return value */
3662 : int temp = 0;
3663 :
3664 : /* We shall not remove data before checking that everything is there. */
3665 1 : temp = dlt_receiver_check_and_get(rec, &userapp, len, DLT_RCV_SKIP_HEADER);
3666 :
3667 1 : if (temp < 0)
3668 : /* Not enough bytes received */
3669 0 : return -1;
3670 : else {
3671 1 : to_remove = (uint32_t)temp;
3672 : }
3673 :
3674 1 : len = userapp.description_length;
3675 :
3676 1 : if (len > DLT_DAEMON_DESCSIZE) {
3677 : len = DLT_DAEMON_DESCSIZE;
3678 0 : dlt_log(LOG_WARNING, "Application description exceeds limit\n");
3679 : }
3680 :
3681 : /* adjust buffer pointer */
3682 1 : rec->buf += to_remove + sizeof(DltUserHeader);
3683 :
3684 1 : if (dlt_receiver_check_and_get(rec, description, len, DLT_RCV_NONE) < 0) {
3685 0 : dlt_log(LOG_ERR, "Unable to get application description\n");
3686 : /* in case description was not readable, set dummy description */
3687 : memcpy(description, "Unknown", sizeof("Unknown"));
3688 :
3689 : /* unknown len of original description, set to 0 to not remove in next
3690 : * step. Because message buffer is re-adjusted the corrupted description
3691 : * is ignored. */
3692 : len = 0;
3693 : }
3694 :
3695 : /* adjust to_remove */
3696 1 : to_remove += (uint32_t)sizeof(DltUserHeader) + len;
3697 : /* point to begin of message */
3698 1 : rec->buf = origin;
3699 :
3700 : /* We can now remove data. */
3701 1 : if (dlt_receiver_remove(rec, (int)to_remove) != DLT_RETURN_OK) {
3702 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n");
3703 0 : return -1;
3704 : }
3705 :
3706 1 : old_application = dlt_daemon_application_find(daemon, userapp.apid, daemon->ecuid, verbose);
3707 :
3708 1 : if (old_application != NULL)
3709 0 : old_pid = old_application->pid;
3710 :
3711 1 : if (rec->type == DLT_RECEIVE_SOCKET)
3712 0 : fd = rec->fd; /* For sockets, an app specific fd has already been created with accept(). */
3713 :
3714 : application =
3715 1 : dlt_daemon_application_add(daemon, userapp.apid, userapp.pid, description, fd, daemon->ecuid, verbose);
3716 :
3717 : /* send log state to new application */
3718 1 : dlt_daemon_user_send_log_state(daemon, application, verbose);
3719 :
3720 1 : if (application == NULL) {
3721 0 : dlt_vlog(LOG_WARNING, "Can't add ApplicationID '%.4s' for PID %d\n", userapp.apid, userapp.pid);
3722 0 : return -1;
3723 1 : } else if (old_pid != application->pid) {
3724 1 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = {'\0'};
3725 :
3726 1 : snprintf(
3727 : local_str, DLT_DAEMON_TEXTBUFSIZE, "ApplicationID '%.4s' registered for PID %d, Description=%s",
3728 1 : application->apid, application->pid, application->application_description);
3729 1 : dlt_daemon_log_internal(
3730 : daemon, daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
3731 : daemon_local->flags.vflag);
3732 1 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
3733 : }
3734 :
3735 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
3736 : if (dlt_daemon_user_send_trace_load_config(daemon, application, verbose) != DLT_RETURN_OK)
3737 : dlt_vlog(
3738 : LOG_WARNING, "Cannot send trace config to Apid: %.4s, PID: %d\n", application->apid, application->pid);
3739 : #endif
3740 : } else {
3741 0 : dlt_vlog(LOG_ERR, "Unsupported DLT version %u in %s\n", daemon->daemon_version, __func__);
3742 0 : return -1;
3743 : }
3744 : return 0;
3745 : }
3746 :
3747 2 : int dlt_daemon_process_user_message_register_context(
3748 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* rec, int verbose)
3749 : {
3750 : uint32_t to_remove = 0;
3751 : uint32_t len = (uint32_t)(sizeof(DltUserControlMsgRegisterContext));
3752 : DltUserControlMsgRegisterContext userctxt;
3753 2 : char description[DLT_DAEMON_DESCSIZE + 1] = {'\0'};
3754 2 : DltDaemonApplication* application = NULL;
3755 : DltDaemonContext* context = NULL;
3756 : char* origin;
3757 :
3758 2 : PRINT_FUNCTION_VERBOSE(verbose);
3759 :
3760 2 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
3761 0 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__);
3762 0 : return -1;
3763 : }
3764 :
3765 2 : if (daemon->daemon_version == DLTProtocolV2) {
3766 : DltUserControlMsgRegisterContextV2 usercontext;
3767 : /* local request pointer removed to avoid overlaying small buffers */
3768 : memset(&usercontext, 0, sizeof(DltUserControlMsgRegisterContextV2));
3769 : usercontext.apid = NULL;
3770 : usercontext.ctid = NULL;
3771 : int usercontextSize;
3772 : uint8_t* buffer;
3773 : DltMessageV2 msg;
3774 : int offset = 0;
3775 :
3776 0 : PRINT_FUNCTION_VERBOSE(verbose);
3777 :
3778 0 : usercontext.apidlen = (uint8_t)rec->buf[8]; // TBD: write function to get apidlen from received buffer
3779 0 : usercontext.ctidlen =
3780 0 : (uint8_t)rec->buf[9 + usercontext.apidlen]; // TBD: write function to get ctidlen from received buffer
3781 :
3782 : usercontextSize =
3783 0 : (int)(sizeof(uint8_t) + usercontext.apidlen + sizeof(uint8_t) + usercontext.ctidlen + 10 + sizeof(pid_t));
3784 : len = (uint32_t)usercontextSize;
3785 0 : buffer = (uint8_t*)malloc((size_t)usercontextSize);
3786 :
3787 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
3788 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__);
3789 : free(buffer);
3790 0 : return -1;
3791 : }
3792 :
3793 : origin = rec->buf;
3794 :
3795 : /* Adding temp variable to check the return value */
3796 : int temp = 0;
3797 :
3798 0 : temp = dlt_receiver_check_and_get(rec, buffer, (unsigned int)len, DLT_RCV_SKIP_HEADER);
3799 :
3800 0 : if (temp < 0) {
3801 : /* Not enough bytes received */
3802 0 : free(buffer);
3803 0 : return -1;
3804 : } else {
3805 0 : to_remove = (uint32_t)temp;
3806 : }
3807 :
3808 : memcpy(&(usercontext.apidlen), buffer, 1);
3809 : offset = 1;
3810 :
3811 0 : usercontext.apid = (char*)malloc((size_t)usercontext.apidlen + 1);
3812 0 : if (usercontext.apid == NULL) {
3813 0 : dlt_log(LOG_ERR, "Memory allocation failed for usercontext.apid\n");
3814 0 : free(buffer);
3815 0 : return -1;
3816 : }
3817 0 : memcpy(usercontext.apid, (buffer + offset), usercontext.apidlen);
3818 0 : memset((usercontext.apid + usercontext.apidlen), '\0', 1); // Null-terminate string
3819 0 : offset += usercontext.apidlen;
3820 0 : memcpy(&(usercontext.ctidlen), (buffer + offset), 1);
3821 0 : offset += 1;
3822 0 : usercontext.ctid = (char*)malloc((size_t)usercontext.ctidlen + 1);
3823 0 : if (usercontext.ctid == NULL) {
3824 0 : dlt_log(LOG_ERR, "Memory allocation failed for usercontext.ctid\n");
3825 0 : free(usercontext.apid);
3826 0 : free(buffer);
3827 0 : return -1;
3828 : }
3829 0 : memcpy(usercontext.ctid, (buffer + offset), usercontext.ctidlen);
3830 0 : memset((usercontext.ctid + usercontext.ctidlen), '\0', 1); // Null-terminate string
3831 0 : offset += usercontext.ctidlen;
3832 0 : memcpy(&(usercontext.log_level_pos), (buffer + offset), sizeof(int32_t));
3833 0 : offset += (int)sizeof(int32_t);
3834 0 : memcpy(&(usercontext.log_level), (buffer + offset), sizeof(int8_t));
3835 0 : offset += (int)sizeof(int8_t);
3836 0 : memcpy(&(usercontext.trace_status), (buffer + offset), sizeof(int8_t));
3837 0 : offset += (int)sizeof(int8_t);
3838 0 : memcpy(&(usercontext.pid), (buffer + offset), sizeof(pid_t));
3839 0 : offset += (int)sizeof(pid_t);
3840 0 : memcpy(&(usercontext.description_length), (buffer + offset), 4);
3841 :
3842 : len = usercontext.description_length;
3843 :
3844 0 : if (len > DLT_DAEMON_DESCSIZE) {
3845 0 : dlt_vlog(LOG_WARNING, "Context description exceeds limit: %u\n", len);
3846 : len = DLT_DAEMON_DESCSIZE;
3847 : }
3848 :
3849 : /* adjust buffer pointer */
3850 0 : rec->buf += to_remove + sizeof(DltUserHeader);
3851 :
3852 0 : if (dlt_receiver_check_and_get(rec, description, len, DLT_RCV_NONE) < 0) {
3853 0 : dlt_log(LOG_ERR, "Unable to get context description\n");
3854 : /* in case description was not readable, set dummy description */
3855 : memcpy(description, "Unknown", sizeof("Unknown"));
3856 :
3857 : /* unknown len of original description, set to 0 to not remove in next
3858 : * step. Because message buffer is re-adjusted the corrupted description
3859 : * is ignored. */
3860 : len = 0;
3861 : }
3862 :
3863 : /* adjust to_remove */
3864 0 : to_remove += (uint32_t)sizeof(DltUserHeader) + len;
3865 : /* point to begin of message */
3866 0 : rec->buf = origin;
3867 :
3868 : /* We can now remove data. */
3869 0 : if (dlt_receiver_remove(rec, (int)to_remove) != DLT_RETURN_OK) {
3870 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n");
3871 0 : free(usercontext.apid);
3872 0 : free(usercontext.ctid);
3873 0 : free(buffer);
3874 0 : return -1;
3875 : }
3876 :
3877 0 : dlt_daemon_application_find_v2(
3878 0 : daemon, usercontext.apidlen, usercontext.apid, daemon->ecuid2len, daemon->ecuid2, verbose, &application);
3879 :
3880 0 : if (application == NULL) {
3881 0 : dlt_vlog(
3882 : LOG_WARNING, "ApID '%s' not found for new ContextID '%s' in %s\n", usercontext.apid, usercontext.ctid,
3883 : __func__);
3884 :
3885 0 : free(usercontext.apid);
3886 0 : free(usercontext.ctid);
3887 0 : free(buffer);
3888 0 : return 0;
3889 : }
3890 :
3891 : /* Set log level */
3892 0 : if (usercontext.log_level == DLT_USER_LOG_LEVEL_NOT_SET) {
3893 0 : usercontext.log_level = DLT_LOG_DEFAULT;
3894 : } else {
3895 : /* Plausibility check */
3896 0 : if ((usercontext.log_level < DLT_LOG_DEFAULT) || (usercontext.log_level > DLT_LOG_VERBOSE)) {
3897 0 : free(usercontext.apid);
3898 0 : free(usercontext.ctid);
3899 0 : free(buffer);
3900 0 : return -1;
3901 : }
3902 : }
3903 :
3904 : /* Set trace status */
3905 0 : if (usercontext.trace_status == DLT_USER_TRACE_STATUS_NOT_SET) {
3906 0 : usercontext.trace_status = DLT_TRACE_STATUS_DEFAULT;
3907 : } else {
3908 : /* Plausibility check */
3909 0 : if ((usercontext.trace_status < DLT_TRACE_STATUS_DEFAULT)
3910 0 : || (usercontext.trace_status > DLT_TRACE_STATUS_ON)) {
3911 0 : free(usercontext.apid);
3912 0 : free(usercontext.ctid);
3913 0 : free(buffer);
3914 0 : return -1;
3915 : }
3916 : }
3917 :
3918 0 : context = dlt_daemon_context_add_v2(
3919 0 : daemon, usercontext.apidlen, usercontext.apid, usercontext.ctidlen, usercontext.ctid, usercontext.log_level,
3920 0 : usercontext.trace_status, usercontext.log_level_pos, application->user_handle, description,
3921 0 : daemon->ecuid2len, daemon->ecuid2, verbose);
3922 0 : if (context == NULL) {
3923 0 : dlt_vlog(
3924 : LOG_WARNING, "Can't add ContextID '%s' for ApID '%s'\n in %s", usercontext.ctid, usercontext.apid,
3925 : __func__);
3926 0 : free(usercontext.apid);
3927 0 : free(usercontext.ctid);
3928 0 : free(buffer);
3929 0 : return -1;
3930 : } else {
3931 0 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = {'\0'};
3932 :
3933 0 : snprintf(
3934 : local_str, DLT_DAEMON_TEXTBUFSIZE, "ContextID '%s' registered for ApID '%s', Description=%s",
3935 : context->ctid2, context->apid2, context->context_description);
3936 :
3937 0 : if (verbose)
3938 0 : dlt_daemon_log_internal(
3939 : daemon, daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID, verbose);
3940 :
3941 0 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
3942 : }
3943 0 : if (daemon_local->flags.offlineLogstorageMaxDevices) {
3944 : // TBD: update for DLT V2
3945 : /* Store log level set for offline logstorage into context structure*/
3946 0 : context->storage_log_level = (int8_t)dlt_daemon_logstorage_get_loglevel(
3947 0 : daemon, (int8_t)daemon_local->flags.offlineLogstorageMaxDevices, usercontext.apid, usercontext.ctid);
3948 : } else
3949 0 : context->storage_log_level = DLT_LOG_DEFAULT;
3950 :
3951 : /* Create automatic get log info response for registered context */
3952 0 : if (daemon_local->flags.rflag) {
3953 : /* Prepare request for get log info with one application and one context */
3954 0 : if (dlt_message_init_v2(&msg, verbose) == -1) {
3955 0 : dlt_log(LOG_WARNING, "Can't initialize message");
3956 0 : return -1;
3957 : }
3958 :
3959 0 : msg.datasize = (int)(sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint8_t) + usercontext.apidlen
3960 0 : + sizeof(uint8_t) + usercontext.ctidlen + DLT_ID_SIZE);
3961 :
3962 0 : if (msg.databuffer && (msg.databuffersize < msg.datasize)) {
3963 0 : free(msg.databuffer);
3964 0 : msg.databuffer = 0;
3965 : }
3966 :
3967 0 : if (msg.databuffer == 0) {
3968 0 : msg.databuffer = (uint8_t*)malloc((size_t)msg.datasize);
3969 0 : msg.databuffersize = msg.datasize;
3970 : }
3971 :
3972 0 : if (msg.databuffer == 0) {
3973 0 : dlt_log(LOG_WARNING, "Can't allocate buffer for get log info message\n");
3974 0 : return -1;
3975 : }
3976 :
3977 : /* prepare local request values (do NOT overlay struct onto small buffer) */
3978 : DltServiceGetLogInfoRequestV2 req_local;
3979 : char apid_buf[DLT_V2_ID_SIZE];
3980 : char ctid_buf[DLT_V2_ID_SIZE];
3981 : char com_buf[DLT_ID_SIZE];
3982 :
3983 0 : req_local.service_id = DLT_SERVICE_ID_GET_LOG_INFO;
3984 0 : req_local.options = (uint8_t)daemon_local->flags.autoResponseGetLogInfoOption;
3985 0 : req_local.apidlen = usercontext.apidlen;
3986 0 : req_local.ctidlen = usercontext.ctidlen;
3987 : /* fill id buffers */
3988 0 : dlt_set_id_v2(apid_buf, usercontext.apid, req_local.apidlen);
3989 0 : dlt_set_id_v2(ctid_buf, usercontext.ctid, req_local.ctidlen);
3990 0 : dlt_set_id(com_buf, "remo");
3991 :
3992 : offset = 0;
3993 0 : memcpy(msg.databuffer + offset, &(req_local.service_id), sizeof(uint32_t));
3994 : offset += (int)sizeof(uint32_t);
3995 0 : memcpy(msg.databuffer + offset, &(req_local.options), sizeof(uint8_t));
3996 : offset += (int)sizeof(uint8_t);
3997 0 : memcpy(msg.databuffer + offset, &(req_local.apidlen), sizeof(uint8_t));
3998 : offset += (int)sizeof(uint8_t);
3999 0 : if (req_local.apidlen > 0)
4000 0 : memcpy(msg.databuffer + offset, apid_buf, req_local.apidlen);
4001 0 : offset += req_local.apidlen;
4002 0 : memcpy(msg.databuffer + offset, &(req_local.ctidlen), sizeof(uint8_t));
4003 0 : offset += (int)sizeof(uint8_t);
4004 0 : if (req_local.ctidlen > 0)
4005 0 : memcpy(msg.databuffer + offset, ctid_buf, req_local.ctidlen);
4006 0 : offset += req_local.ctidlen;
4007 0 : memcpy(msg.databuffer + offset, com_buf, DLT_ID_SIZE);
4008 : offset = 0;
4009 :
4010 0 : dlt_daemon_control_get_log_info_v2(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, &msg, verbose);
4011 0 : dlt_message_free_v2(&msg, verbose);
4012 : }
4013 :
4014 0 : if (context->user_handle >= DLT_FD_MINIMUM) {
4015 0 : if ((usercontext.log_level == DLT_LOG_DEFAULT) || (usercontext.trace_status == DLT_TRACE_STATUS_DEFAULT)) {
4016 : /* This call also replaces the default values with the values defined for default */
4017 0 : if (dlt_daemon_user_send_log_level_v2(daemon, context, verbose) == -1) {
4018 0 : dlt_vlog(
4019 : LOG_WARNING, "Can't send current log level as response to %s for (%s;%s)\n", __func__,
4020 0 : context->apid, context->ctid);
4021 0 : free(usercontext.apid);
4022 0 : free(usercontext.ctid);
4023 0 : free(buffer);
4024 0 : return -1;
4025 : }
4026 : }
4027 : }
4028 0 : free(usercontext.apid);
4029 0 : free(usercontext.ctid);
4030 0 : free(buffer);
4031 2 : } else if (daemon->daemon_version == DLTProtocolV1) {
4032 : DltMessage msg;
4033 : DltServiceGetLogInfoRequest* req = NULL;
4034 : memset(&userctxt, 0, sizeof(DltUserControlMsgRegisterContext));
4035 2 : origin = rec->buf;
4036 :
4037 : /* Adding temp variable to check the return value */
4038 : int temp = 0;
4039 :
4040 2 : temp = dlt_receiver_check_and_get(rec, &userctxt, len, DLT_RCV_SKIP_HEADER);
4041 :
4042 2 : if (temp < 0)
4043 : /* Not enough bytes received */
4044 0 : return -1;
4045 : else {
4046 2 : to_remove = (uint32_t)temp;
4047 : }
4048 :
4049 2 : len = userctxt.description_length;
4050 :
4051 2 : if (len > DLT_DAEMON_DESCSIZE) {
4052 0 : dlt_vlog(LOG_WARNING, "Context description exceeds limit: %u\n", len);
4053 : len = DLT_DAEMON_DESCSIZE;
4054 : }
4055 :
4056 : /* adjust buffer pointer */
4057 2 : rec->buf += to_remove + sizeof(DltUserHeader);
4058 :
4059 2 : if (dlt_receiver_check_and_get(rec, description, len, DLT_RCV_NONE) < 0) {
4060 0 : dlt_log(LOG_ERR, "Unable to get context description\n");
4061 : /* in case description was not readable, set dummy description */
4062 : memcpy(description, "Unknown", sizeof("Unknown"));
4063 :
4064 : /* unknown len of original description, set to 0 to not remove in next
4065 : * step. Because message buffer is re-adjusted the corrupted description
4066 : * is ignored. */
4067 : len = 0;
4068 : }
4069 :
4070 : /* adjust to_remove */
4071 2 : to_remove += (uint32_t)sizeof(DltUserHeader) + len;
4072 : /* point to begin of message */
4073 2 : rec->buf = origin;
4074 :
4075 : /* We can now remove data. */
4076 2 : if (dlt_receiver_remove(rec, (int)to_remove) != DLT_RETURN_OK) {
4077 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n");
4078 0 : return -1;
4079 : }
4080 :
4081 2 : application = dlt_daemon_application_find(daemon, userctxt.apid, daemon->ecuid, verbose);
4082 :
4083 2 : if (application == 0) {
4084 0 : dlt_vlog(
4085 : LOG_WARNING, "ApID '%.4s' not found for new ContextID '%.4s' in %s\n", userctxt.apid, userctxt.ctid,
4086 : __func__);
4087 :
4088 0 : return 0;
4089 : }
4090 :
4091 : /* Set log level */
4092 2 : if (userctxt.log_level == DLT_USER_LOG_LEVEL_NOT_SET) {
4093 2 : userctxt.log_level = DLT_LOG_DEFAULT;
4094 : } else {
4095 : /* Plausibility check */
4096 0 : if ((userctxt.log_level < DLT_LOG_DEFAULT) || (userctxt.log_level > DLT_LOG_VERBOSE)) {
4097 : return -1;
4098 : }
4099 : }
4100 :
4101 : /* Set trace status */
4102 2 : if (userctxt.trace_status == DLT_USER_TRACE_STATUS_NOT_SET) {
4103 2 : userctxt.trace_status = DLT_TRACE_STATUS_DEFAULT;
4104 : } else {
4105 : /* Plausibility check */
4106 0 : if ((userctxt.trace_status < DLT_TRACE_STATUS_DEFAULT) || (userctxt.trace_status > DLT_TRACE_STATUS_ON)) {
4107 : return -1;
4108 : }
4109 : }
4110 :
4111 2 : context = dlt_daemon_context_add(
4112 2 : daemon, userctxt.apid, userctxt.ctid, userctxt.log_level, userctxt.trace_status, userctxt.log_level_pos,
4113 : application->user_handle, description, daemon->ecuid, verbose);
4114 :
4115 2 : if (context == 0) {
4116 0 : dlt_vlog(
4117 : LOG_WARNING, "Can't add ContextID '%.4s' for ApID '%.4s'\n in %s", userctxt.ctid, userctxt.apid,
4118 : __func__);
4119 0 : return -1;
4120 : } else {
4121 2 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = {'\0'};
4122 :
4123 2 : snprintf(
4124 : local_str, DLT_DAEMON_TEXTBUFSIZE, "ContextID '%.4s' registered for ApID '%.4s', Description=%s",
4125 2 : context->ctid, context->apid, context->context_description);
4126 :
4127 2 : if (verbose)
4128 0 : dlt_daemon_log_internal(
4129 : daemon, daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID, verbose);
4130 :
4131 2 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
4132 : }
4133 :
4134 2 : if (daemon_local->flags.offlineLogstorageMaxDevices)
4135 : /* Store log level set for offline logstorage into context structure*/
4136 2 : context->storage_log_level = (int8_t)dlt_daemon_logstorage_get_loglevel(
4137 2 : daemon, (int8_t)daemon_local->flags.offlineLogstorageMaxDevices, userctxt.apid, userctxt.ctid);
4138 : else
4139 0 : context->storage_log_level = DLT_LOG_DEFAULT;
4140 :
4141 : /* Create automatic get log info response for registered context */
4142 2 : if (daemon_local->flags.rflag) {
4143 : /* Prepare request for get log info with one application and one context */
4144 0 : if (dlt_message_init(&msg, verbose) == -1) {
4145 0 : dlt_log(LOG_WARNING, "Can't initialize message");
4146 0 : return -1;
4147 : }
4148 :
4149 0 : msg.datasize = sizeof(DltServiceGetLogInfoRequest);
4150 :
4151 0 : if (msg.databuffer && (msg.databuffersize < msg.datasize)) {
4152 0 : free(msg.databuffer);
4153 0 : msg.databuffer = 0;
4154 : }
4155 :
4156 0 : if (msg.databuffer == 0) {
4157 0 : msg.databuffer = (uint8_t*)malloc((size_t)msg.datasize);
4158 0 : msg.databuffersize = msg.datasize;
4159 : }
4160 :
4161 0 : if (msg.databuffer == 0) {
4162 0 : dlt_log(LOG_WARNING, "Can't allocate buffer for get log info message\n");
4163 0 : return -1;
4164 : }
4165 :
4166 : req = (DltServiceGetLogInfoRequest*)msg.databuffer;
4167 :
4168 0 : req->service_id = DLT_SERVICE_ID_GET_LOG_INFO;
4169 0 : req->options = (uint8_t)daemon_local->flags.autoResponseGetLogInfoOption;
4170 0 : dlt_set_id(req->apid, userctxt.apid);
4171 0 : dlt_set_id(req->ctid, userctxt.ctid);
4172 0 : dlt_set_id(req->com, "remo");
4173 :
4174 0 : dlt_daemon_control_get_log_info(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, &msg, verbose);
4175 :
4176 0 : dlt_message_free(&msg, verbose);
4177 : }
4178 :
4179 2 : if (context->user_handle >= DLT_FD_MINIMUM) {
4180 2 : if ((userctxt.log_level == DLT_LOG_DEFAULT) || (userctxt.trace_status == DLT_TRACE_STATUS_DEFAULT)) {
4181 : /* This call also replaces the default values with the values defined for default */
4182 2 : if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) {
4183 0 : dlt_vlog(
4184 : LOG_WARNING, "Can't send current log level as response to %s for (%.4s;%.4s)\n", __func__,
4185 : context->apid, context->ctid);
4186 0 : return -1;
4187 : }
4188 : }
4189 : }
4190 : } else {
4191 0 : dlt_vlog(LOG_ERR, "Unsupported DLT version %u in %s\n", daemon->daemon_version, __func__);
4192 0 : return -1;
4193 : }
4194 :
4195 : return 0;
4196 : }
4197 :
4198 0 : int dlt_daemon_process_user_message_unregister_application(
4199 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* rec, int verbose)
4200 : {
4201 0 : DltDaemonApplication* application = NULL;
4202 : DltDaemonContext* context;
4203 : int i, offset_base;
4204 : DltDaemonRegisteredUsers* user_list = NULL;
4205 :
4206 0 : PRINT_FUNCTION_VERBOSE(verbose);
4207 :
4208 0 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
4209 0 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__);
4210 0 : return -1;
4211 : }
4212 :
4213 0 : if (daemon->daemon_version == DLTProtocolV2) {
4214 : uint32_t len = sizeof(DltUserControlMsgUnregisterApplicationV2);
4215 : DltUserControlMsgUnregisterApplicationV2 userapp;
4216 : int userappSize;
4217 : uint8_t* buffer;
4218 0 : userapp.apidlen = (uint8_t)rec->buf[8]; // TBD: write function to get apidlen from received buffer
4219 0 : userapp.apid = NULL;
4220 0 : userappSize = (int)sizeof(uint8_t) + userapp.apidlen + (int)sizeof(pid_t);
4221 0 : len = (uint32_t)userappSize;
4222 0 : buffer = (uint8_t*)malloc((size_t)userappSize);
4223 :
4224 : int offset = 0;
4225 :
4226 0 : if (dlt_receiver_check_and_get(rec, buffer, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
4227 : /* Not enough bytes received */
4228 0 : return -1;
4229 :
4230 : memcpy(&(userapp.apidlen), buffer, 1);
4231 : offset = 1;
4232 : char apid_buf[DLT_V2_ID_SIZE];
4233 0 : dlt_set_id_v2(apid_buf, (const char*)(buffer + offset), userapp.apidlen);
4234 0 : userapp.apid = apid_buf;
4235 0 : offset += userapp.apidlen;
4236 0 : memcpy(&(userapp.pid), (buffer + offset), sizeof(pid_t));
4237 0 : user_list = dlt_daemon_find_users_list_v2(daemon, daemon->ecuid2len, daemon->ecuid2, verbose);
4238 :
4239 0 : if (user_list == NULL)
4240 : return -1;
4241 :
4242 0 : if (user_list->num_applications > 0) {
4243 : /* Delete this application and all corresponding contexts
4244 : * for this application from internal table.
4245 : */
4246 0 : dlt_daemon_application_find_v2(
4247 0 : daemon, userapp.apidlen, userapp.apid, daemon->ecuid2len, daemon->ecuid2, verbose, &application);
4248 0 : if (application != NULL) {
4249 : /* Calculate start offset within contexts[] */
4250 : offset_base = 0;
4251 0 : for (i = 0; i < (application - (user_list->applications)); i++)
4252 0 : offset_base += user_list->applications[i].num_contexts;
4253 0 : for (i = (application->num_contexts) - 1; i >= 0; i--) {
4254 0 : context = &(user_list->contexts[offset_base + i]);
4255 0 : if (context) {
4256 : /* Delete context */
4257 0 : if (dlt_daemon_context_del_v2(daemon, context, daemon->ecuid2len, daemon->ecuid2, verbose)
4258 : == -1) {
4259 0 : dlt_vlog(
4260 0 : LOG_WARNING, "Can't delete CtID '%s' for ApID '%s' in %s\n", context->ctid,
4261 0 : context->apid, __func__);
4262 0 : return -1;
4263 : }
4264 : }
4265 : }
4266 : /* Delete this application entry from internal table*/
4267 0 : if (dlt_daemon_application_del_v2(daemon, application, daemon->ecuid2len, daemon->ecuid2, verbose)
4268 : == -1) {
4269 0 : dlt_vlog(LOG_WARNING, "Can't delete ApID '%s' in %s\n", application->apid, __func__);
4270 0 : return -1;
4271 : } else {
4272 0 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = {'\0'};
4273 : snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "Unregistered ApID '%s'", userapp.apid);
4274 0 : dlt_daemon_log_internal(
4275 : daemon, daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID, verbose);
4276 0 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
4277 : }
4278 : }
4279 : }
4280 0 : } else if (daemon->daemon_version == DLTProtocolV1) {
4281 : uint32_t len = sizeof(DltUserControlMsgUnregisterApplication);
4282 : DltUserControlMsgUnregisterApplication userapp;
4283 0 : if (dlt_receiver_check_and_get(rec, &userapp, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
4284 : /* Not enough bytes received */
4285 0 : return -1;
4286 :
4287 0 : user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
4288 :
4289 0 : if (user_list == NULL)
4290 : return -1;
4291 :
4292 0 : if (user_list->num_applications > 0) {
4293 : /* Delete this application and all corresponding contexts
4294 : * for this application from internal table.
4295 : */
4296 0 : application = dlt_daemon_application_find(daemon, userapp.apid, daemon->ecuid, verbose);
4297 :
4298 0 : if (application) {
4299 : /* Calculate start offset within contexts[] */
4300 : offset_base = 0;
4301 :
4302 0 : for (i = 0; i < (application - (user_list->applications)); i++)
4303 0 : offset_base += user_list->applications[i].num_contexts;
4304 :
4305 0 : for (i = (application->num_contexts) - 1; i >= 0; i--) {
4306 0 : context = &(user_list->contexts[offset_base + i]);
4307 :
4308 0 : if (context) {
4309 : /* Delete context */
4310 0 : if (dlt_daemon_context_del(daemon, context, daemon->ecuid, verbose) == -1) {
4311 0 : dlt_vlog(
4312 0 : LOG_WARNING, "Can't delete CtID '%.4s' for ApID '%.4s' in %s\n", context->ctid,
4313 0 : context->apid, __func__);
4314 0 : return -1;
4315 : }
4316 : }
4317 : }
4318 :
4319 : /* Delete this application entry from internal table*/
4320 0 : if (dlt_daemon_application_del(daemon, application, daemon->ecuid, verbose) == -1) {
4321 0 : dlt_vlog(LOG_WARNING, "Can't delete ApID '%.4s' in %s\n", application->apid, __func__);
4322 0 : return -1;
4323 : } else {
4324 0 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = {'\0'};
4325 :
4326 : snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "Unregistered ApID '%.4s'", userapp.apid);
4327 0 : dlt_daemon_log_internal(
4328 : daemon, daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID, verbose);
4329 0 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
4330 : }
4331 : }
4332 : }
4333 : } else {
4334 0 : dlt_vlog(LOG_ERR, "Unsupported DLT version %u in %s\n", daemon->daemon_version, __func__);
4335 0 : return -1;
4336 : }
4337 :
4338 : return 0;
4339 : }
4340 :
4341 0 : int dlt_daemon_process_user_message_unregister_context(
4342 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* rec, int verbose)
4343 : {
4344 : DltUserControlMsgUnregisterContext userctxt;
4345 : DltDaemonContext* context;
4346 :
4347 0 : PRINT_FUNCTION_VERBOSE(verbose);
4348 :
4349 0 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
4350 0 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__);
4351 :
4352 0 : return -1;
4353 : }
4354 :
4355 0 : if (daemon->daemon_version == DLTProtocolV2) {
4356 : uint32_t len = sizeof(DltUserControlMsgUnregisterContextV2);
4357 : DltUserControlMsgUnregisterContextV2 usercontext;
4358 : int usercontextSize;
4359 : uint8_t* buffer;
4360 0 : usercontext.apid = NULL;
4361 0 : usercontext.ctid = NULL;
4362 0 : usercontext.apidlen = (uint8_t)rec->buf[8]; // TBD: write function to get apidlen from received buffer
4363 0 : usercontext.ctidlen =
4364 0 : (uint8_t)rec->buf[9 + usercontext.apidlen]; // TBD: write function to get ctidlen from received buffer
4365 : usercontextSize =
4366 0 : (int)(sizeof(uint8_t) + usercontext.apidlen + sizeof(uint8_t) + usercontext.ctidlen + sizeof(pid_t));
4367 : len = (uint32_t)usercontextSize;
4368 0 : buffer = (uint8_t*)malloc((size_t)usercontextSize);
4369 :
4370 : int offset = 0;
4371 :
4372 0 : if (dlt_receiver_check_and_get(rec, buffer, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0) {
4373 : /* Not enough bytes received */
4374 0 : return -1;
4375 : }
4376 :
4377 : memcpy(&(usercontext.apidlen), buffer, 1);
4378 : offset = 1;
4379 0 : dlt_set_id_v2(usercontext.apid, (const char*)(buffer + offset), usercontext.apidlen);
4380 0 : offset += usercontext.apidlen;
4381 0 : memcpy(&(usercontext.ctidlen), (buffer + offset), 1);
4382 0 : offset += 1;
4383 0 : dlt_set_id_v2(usercontext.ctid, (const char*)(buffer + offset), usercontext.ctidlen);
4384 0 : offset += usercontext.ctidlen;
4385 0 : memcpy(&(usercontext.pid), (buffer + offset), sizeof(pid_t));
4386 : offset += (int)sizeof(pid_t);
4387 :
4388 0 : context = dlt_daemon_context_find_v2(
4389 0 : daemon, usercontext.apidlen, usercontext.apid, usercontext.ctidlen, usercontext.ctid, daemon->ecuid2len,
4390 0 : daemon->ecuid2, verbose);
4391 :
4392 :
4393 : /* In case the daemon is loaded with predefined contexts and its context
4394 : * unregisters, the context information will not be deleted from daemon's
4395 : * table until its parent application is unregistered.
4396 : */
4397 0 : if (context && (context->predefined == false)) {
4398 : /* Delete this connection entry from internal table*/
4399 0 : if (dlt_daemon_context_del_v2(daemon, context, daemon->ecuid2len, daemon->ecuid2, verbose) == -1) {
4400 0 : dlt_vlog(
4401 : LOG_WARNING, "Can't delete CtID '%s' for ApID '%s' in %s\n",
4402 : usercontext.ctid ? usercontext.ctid : "<NULL>", usercontext.apid ? usercontext.apid : "<NULL>",
4403 : __func__);
4404 0 : return -1;
4405 : } else {
4406 0 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = {'\0'};
4407 :
4408 : snprintf(
4409 : local_str, DLT_DAEMON_TEXTBUFSIZE, "Unregistered CtID '%s' for ApID '%s'",
4410 : usercontext.ctid ? usercontext.ctid : "<NULL>", usercontext.apid ? usercontext.apid : "<NULL>");
4411 :
4412 0 : if (verbose) {
4413 0 : dlt_daemon_log_internal(
4414 : daemon, daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID, verbose);
4415 : }
4416 :
4417 0 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
4418 : }
4419 : }
4420 :
4421 : /* Create automatic unregister context response for unregistered context */
4422 0 : if (daemon_local->flags.rflag)
4423 0 : dlt_daemon_control_message_unregister_context_v2(
4424 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, usercontext.apidlen, usercontext.apid,
4425 : usercontext.ctidlen, usercontext.ctid, "remo", verbose);
4426 0 : } else if (daemon->daemon_version == DLTProtocolV1) {
4427 : uint32_t len = sizeof(DltUserControlMsgUnregisterContext);
4428 0 : if (dlt_receiver_check_and_get(rec, &userctxt, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
4429 : /* Not enough bytes received */
4430 : return -1;
4431 :
4432 0 : context = dlt_daemon_context_find(daemon, userctxt.apid, userctxt.ctid, daemon->ecuid, verbose);
4433 :
4434 : /* In case the daemon is loaded with predefined contexts and its context
4435 : * unregisters, the context information will not be deleted from daemon's
4436 : * table until its parent application is unregistered.
4437 : */
4438 0 : if (context && (context->predefined == false)) {
4439 : /* Delete this connection entry from internal table*/
4440 0 : if (dlt_daemon_context_del(daemon, context, daemon->ecuid, verbose) == -1) {
4441 0 : dlt_vlog(
4442 : LOG_WARNING, "Can't delete CtID '%.4s' for ApID '%.4s' in %s\n", userctxt.ctid, userctxt.apid,
4443 : __func__);
4444 0 : return -1;
4445 : } else {
4446 0 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = {'\0'};
4447 :
4448 : snprintf(
4449 : local_str, DLT_DAEMON_TEXTBUFSIZE, "Unregistered CtID '%.4s' for ApID '%.4s'", userctxt.ctid,
4450 : userctxt.apid);
4451 :
4452 0 : if (verbose)
4453 0 : dlt_daemon_log_internal(
4454 : daemon, daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID, verbose);
4455 :
4456 0 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
4457 : }
4458 : }
4459 :
4460 : /* Create automatic unregister context response for unregistered context */
4461 0 : if (daemon_local->flags.rflag)
4462 0 : dlt_daemon_control_message_unregister_context(
4463 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, userctxt.apid, userctxt.ctid, "remo", verbose);
4464 : } else {
4465 0 : dlt_vlog(LOG_ERR, "Unsupported DLT version %u in %s\n", daemon->daemon_version, __func__);
4466 0 : return -1;
4467 : }
4468 : return 0;
4469 : }
4470 :
4471 441 : int dlt_daemon_process_user_message_log(DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* rec, int verbose)
4472 : {
4473 : int ret = 0;
4474 : int size = 0;
4475 : bool keep_message = true;
4476 441 : PRINT_FUNCTION_VERBOSE(verbose);
4477 :
4478 441 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
4479 0 : dlt_vlog(LOG_ERR, "%s: invalid function parameters.\n", __func__);
4480 0 : return DLT_DAEMON_ERROR_UNKNOWN;
4481 : }
4482 :
4483 : #ifdef DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE
4484 : daemon->received_message_since_last_watchdog_interval = 1;
4485 : #endif
4486 :
4487 : /* TODO: Add support for DLTv2 SHM messages */
4488 : #ifdef DLT_SHM_ENABLE
4489 : /** In case of SHM, the header still received via fifo/unix_socket receiver,
4490 : * so we need to remove header from the receiver.
4491 : */
4492 : if (dlt_receiver_remove(rec, sizeof(DltUserHeader)) < 0)
4493 : /* Not enough bytes received to remove*/
4494 : return DLT_DAEMON_ERROR_UNKNOWN;
4495 :
4496 : while (1) {
4497 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
4498 : bool watchdog_triggered = dlt_daemon_trigger_systemd_watchdog_if_necessary(daemon);
4499 : if (watchdog_triggered) {
4500 : dlt_vlog(LOG_WARNING, "%s yields due to watchdog.\n", __func__);
4501 : break;
4502 : }
4503 : #endif
4504 : /* get log message from SHM then store into receiver buffer */
4505 : size = dlt_shm_pull(&(daemon_local->dlt_shm), daemon_local->recv_buf_shm, DLT_SHM_RCV_BUFFER_SIZE);
4506 :
4507 : if (size <= 0)
4508 : break;
4509 :
4510 : ret = dlt_message_read(&(daemon_local->msg), daemon_local->recv_buf_shm, size, 0, verbose);
4511 :
4512 : if (DLT_MESSAGE_ERROR_OK != ret) {
4513 : dlt_shm_remove(&(daemon_local->dlt_shm));
4514 : dlt_log(LOG_WARNING, "failed to read messages from shm.\n");
4515 : return DLT_DAEMON_ERROR_UNKNOWN;
4516 : }
4517 :
4518 : #if defined(DLT_LOG_LEVEL_APP_CONFIG) || defined(DLT_TRACE_LOAD_CTRL_ENABLE)
4519 : DltDaemonApplication* app =
4520 : dlt_daemon_application_find(daemon, daemon_local->msg.extendedheader->apid, daemon->ecuid, verbose);
4521 : #endif
4522 :
4523 : /* discard non-allowed levels if enforcement is on */
4524 : keep_message = enforce_context_ll_and_ts_keep_message(
4525 : daemon_local
4526 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
4527 : ,
4528 : app
4529 : #endif
4530 : );
4531 :
4532 : // check trace_load
4533 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
4534 : keep_message &= trace_load_keep_message(app, size, daemon, daemon_local, verbose);
4535 : #endif
4536 :
4537 : if (keep_message)
4538 : dlt_daemon_client_send_message_to_all_client(daemon, daemon_local, verbose);
4539 :
4540 : if (DLT_DAEMON_ERROR_OK != ret)
4541 : dlt_log(LOG_ERR, "failed to send message to client.\n");
4542 : }
4543 :
4544 : #else /* DLT_SHM_ENABLE */
4545 441 : if (daemon->daemon_version == DLTProtocolV2) {
4546 0 : ret = dlt_message_read_v2(
4547 0 : &(daemon_local->msgv2), (unsigned char*)rec->buf + sizeof(DltUserHeader),
4548 0 : (unsigned int)((unsigned int)rec->bytesRcvd - sizeof(DltUserHeader)), 0, verbose);
4549 0 : if (ret != DLT_MESSAGE_ERROR_OK) {
4550 0 : if (ret != DLT_MESSAGE_ERROR_SIZE)
4551 : /* This is a normal usecase: The daemon reads the data in 10kb chunks.
4552 : * Thus the last trace in this chunk is probably not complete and will be completed
4553 : * with the next chunk read. This happens always when the FIFO is filled with more than 10kb before
4554 : * the daemon is able to read from the FIFO.
4555 : * Thus the loglevel of this message is set to DEBUG.
4556 : * A cleaner solution would be to check more in detail whether the message is not complete (normal
4557 : * usecase) or the headers are corrupted (error case). */
4558 0 : dlt_log(LOG_DEBUG, "Can't read messages from receiver\n");
4559 :
4560 0 : return DLT_DAEMON_ERROR_UNKNOWN;
4561 : }
4562 :
4563 : #if defined(DLT_LOG_LEVEL_APP_CONFIG) || defined(DLT_TRACE_LOAD_CTRL_ENABLE)
4564 : DltDaemonApplication* app = (DltDaemonApplication*)malloc(sizeof(DltDaemonApplication));
4565 : dlt_daemon_application_find_v2(
4566 : daemon, daemon_local->msgv2.extendedheaderv2->apidlen, daemon_local->msgv2.extendedheaderv2->apid,
4567 : daemon->ecuid2len, daemon->ecuid2, verbose, &app);
4568 : #endif
4569 :
4570 : /* discard non-allowed levels if enforcement is on */
4571 0 : keep_message = enforce_context_ll_and_ts_keep_message_v2(
4572 : daemon_local
4573 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
4574 : ,
4575 : app
4576 : #endif
4577 : );
4578 :
4579 : // check trace_load
4580 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
4581 : keep_message &= trace_load_keep_message_v2(app, size, daemon, daemon_local, verbose);
4582 : #endif
4583 0 : if (keep_message) {
4584 0 : dlt_daemon_client_send_message_to_all_client_v2(daemon, daemon_local, verbose);
4585 : }
4586 : /* keep not read data in buffer */
4587 0 : size = (int)(daemon_local->msgv2.headersizev2 + daemon_local->msgv2.datasize + (int32_t)sizeof(DltUserHeader)
4588 0 : - (int32_t)daemon_local->msgv2.storageheadersizev2);
4589 :
4590 0 : if (daemon_local->msgv2.found_serialheader)
4591 : size += (int)sizeof(dltSerialHeader);
4592 :
4593 0 : if (dlt_receiver_remove(rec, size) != DLT_RETURN_OK) {
4594 0 : dlt_log(LOG_WARNING, "failed to remove bytes from receiver.\n");
4595 0 : return DLT_DAEMON_ERROR_UNKNOWN;
4596 : }
4597 441 : } else if (daemon->daemon_version == DLTProtocolV1) {
4598 441 : ret = dlt_message_read(
4599 441 : &(daemon_local->msg), (unsigned char*)rec->buf + sizeof(DltUserHeader),
4600 441 : (unsigned int)((unsigned int)rec->bytesRcvd - sizeof(DltUserHeader)), 0, verbose);
4601 :
4602 441 : if (ret != DLT_MESSAGE_ERROR_OK) {
4603 0 : if (ret != DLT_MESSAGE_ERROR_SIZE)
4604 : /* This is a normal usecase: The daemon reads the data in 10kb chunks.
4605 : * Thus the last trace in this chunk is probably not complete and will be completed
4606 : * with the next chunk read. This happens always when the FIFO is filled with more than 10kb before
4607 : * the daemon is able to read from the FIFO.
4608 : * Thus the loglevel of this message is set to DEBUG.
4609 : * A cleaner solution would be to check more in detail whether the message is not complete (normal
4610 : * usecase) or the headers are corrupted (error case). */
4611 0 : dlt_log(LOG_DEBUG, "Can't read messages from receiver\n");
4612 :
4613 0 : return DLT_DAEMON_ERROR_UNKNOWN;
4614 : }
4615 :
4616 : #if defined(DLT_LOG_LEVEL_APP_CONFIG) || defined(DLT_TRACE_LOAD_CTRL_ENABLE)
4617 : DltDaemonApplication* app =
4618 : dlt_daemon_application_find(daemon, daemon_local->msg.extendedheader->apid, daemon->ecuid, verbose);
4619 : #endif
4620 :
4621 : /* discard non-allowed levels if enforcement is on */
4622 0 : keep_message = enforce_context_ll_and_ts_keep_message(
4623 : daemon_local
4624 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
4625 : ,
4626 : app
4627 : #endif
4628 : );
4629 :
4630 : // check trace_load
4631 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
4632 : keep_message &= trace_load_keep_message(app, size, daemon, daemon_local, verbose);
4633 : #endif
4634 0 : if (keep_message) {
4635 441 : dlt_daemon_client_send_message_to_all_client(daemon, daemon_local, verbose);
4636 : }
4637 :
4638 : /* keep not read data in buffer */
4639 441 : size = (int)((size_t)daemon_local->msg.headersize + (size_t)daemon_local->msg.datasize
4640 441 : - sizeof(DltStorageHeader) + sizeof(DltUserHeader));
4641 :
4642 441 : if (daemon_local->msg.found_serialheader)
4643 : size += (int)sizeof(dltSerialHeader);
4644 :
4645 441 : if (dlt_receiver_remove(rec, size) != DLT_RETURN_OK) {
4646 0 : dlt_log(LOG_WARNING, "failed to remove bytes from receiver.\n");
4647 0 : return DLT_DAEMON_ERROR_UNKNOWN;
4648 : }
4649 : } else {
4650 0 : dlt_vlog(LOG_ERR, "Unsupported DLT version %u in %s\n", daemon->daemon_version, __func__);
4651 0 : return -1;
4652 : }
4653 : #endif /* DLT_SHM_ENABLE */
4654 :
4655 : return DLT_DAEMON_ERROR_OK;
4656 : }
4657 :
4658 0 : bool enforce_context_ll_and_ts_keep_message(
4659 : DltDaemonLocal* daemon_local
4660 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
4661 : ,
4662 : DltDaemonApplication* app
4663 : #endif
4664 : )
4665 : {
4666 441 : if (!daemon_local->flags.enforceContextLLAndTS || !daemon_local->msg.extendedheader) {
4667 : return true;
4668 : }
4669 :
4670 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
4671 : if (app == NULL) {
4672 : return true;
4673 : }
4674 : #endif
4675 :
4676 0 : const int mtin = DLT_GET_MSIN_MTIN(daemon_local->msg.extendedheader->msin);
4677 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
4678 : if (app->num_context_log_level_settings > 0) {
4679 : DltDaemonContextLogSettings* log_settings =
4680 : dlt_daemon_find_app_log_level_config(app, daemon_local->msg.extendedheader->ctid);
4681 :
4682 : if (log_settings != NULL) {
4683 : return mtin <= log_settings->log_level;
4684 : }
4685 : }
4686 : #endif
4687 0 : return mtin <= daemon_local->flags.contextLogLevel;
4688 : }
4689 :
4690 0 : bool enforce_context_ll_and_ts_keep_message_v2(
4691 : DltDaemonLocal* daemon_local
4692 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
4693 : ,
4694 : DltDaemonApplication* app
4695 : #endif
4696 : )
4697 : {
4698 0 : if (!daemon_local->flags.enforceContextLLAndTS) {
4699 : return true;
4700 : }
4701 :
4702 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
4703 : if (app == NULL) {
4704 : return true;
4705 : }
4706 : #endif
4707 :
4708 0 : const int mtin = DLT_GET_MSIN_MTIN(daemon_local->msgv2.headerextrav2.msin);
4709 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
4710 : if (app->num_context_log_level_settings > 0) {
4711 : /* TODO: Call dlt_daemon_find_app_log_level_config_v2 for DLTv2 */
4712 : DltDaemonContextLogSettings* log_settings =
4713 : dlt_daemon_find_app_log_level_config(app, daemon_local->msgv2.extendedheaderv2->ctid);
4714 :
4715 : if (log_settings != NULL) {
4716 : return mtin <= log_settings->log_level;
4717 : }
4718 : }
4719 : #endif
4720 0 : return mtin <= daemon_local->flags.contextLogLevel;
4721 : }
4722 :
4723 :
4724 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
4725 : bool trace_load_keep_message(
4726 : DltDaemonApplication* app, const int size, DltDaemon* const daemon, DltDaemonLocal* const daemon_local, int verbose)
4727 : {
4728 : bool keep_message = true;
4729 : if (app == NULL || !daemon_local->msg.extendedheader) {
4730 : return keep_message;
4731 : }
4732 :
4733 : DltMessage* msg = &daemon_local->msg;
4734 : const int mtin = DLT_GET_MSIN_MTIN(msg->extendedheader->msin);
4735 :
4736 : struct DltTraceLoadLogParams params = {
4737 : daemon,
4738 : daemon_local,
4739 : verbose,
4740 : app->apid,
4741 : };
4742 :
4743 : DltDaemonContext* context =
4744 : dlt_daemon_context_find(daemon, app->apid, msg->extendedheader->ctid, daemon->ecuid, verbose);
4745 :
4746 :
4747 : if (context == NULL) {
4748 : context = dlt_daemon_context_add(
4749 : daemon, app->apid, msg->extendedheader->ctid, daemon->default_log_level, daemon->default_trace_status, 0,
4750 : app->user_handle, "", daemon->ecuid, verbose);
4751 : if (context == NULL) {
4752 : dlt_vlog(
4753 : LOG_WARNING, "Can't add ContextID '%.4s' for ApID '%.4s' in %s\n", msg->extendedheader->ctid, app->apid,
4754 : __func__);
4755 : return false;
4756 : }
4757 : }
4758 :
4759 : pthread_rwlock_wrlock(&trace_load_rw_lock);
4760 : keep_message = dlt_check_trace_load(
4761 : context->trace_load_settings, mtin, msg->headerextra.tmsp, size, dlt_daemon_output_internal_msg,
4762 : (void*)(¶ms));
4763 : pthread_rwlock_unlock(&trace_load_rw_lock);
4764 :
4765 : return keep_message;
4766 : }
4767 : #endif
4768 :
4769 0 : int dlt_daemon_process_user_message_set_app_ll_ts(
4770 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* rec, int verbose)
4771 : {
4772 : uint32_t len = sizeof(DltUserControlMsgAppLogLevelTraceStatus);
4773 : DltUserControlMsgAppLogLevelTraceStatus userctxt;
4774 : DltDaemonApplication* application;
4775 : DltDaemonContext* context;
4776 : int i, offset_base;
4777 : int8_t old_log_level, old_trace_status;
4778 : DltDaemonRegisteredUsers* user_list = NULL;
4779 :
4780 0 : PRINT_FUNCTION_VERBOSE(verbose);
4781 :
4782 0 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
4783 0 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__);
4784 0 : return DLT_RETURN_ERROR;
4785 : }
4786 :
4787 0 : user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
4788 :
4789 0 : if (user_list == NULL)
4790 : return DLT_RETURN_ERROR;
4791 :
4792 : memset(&userctxt, 0, len);
4793 :
4794 0 : if (dlt_receiver_check_and_get(rec, &userctxt, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
4795 : /* Not enough bytes received */
4796 : return DLT_RETURN_ERROR;
4797 :
4798 0 : if (user_list->num_applications > 0) {
4799 : /* Get all contexts with application id matching the received application id */
4800 0 : application = dlt_daemon_application_find(daemon, userctxt.apid, daemon->ecuid, verbose);
4801 :
4802 0 : if (application) {
4803 : /* Calculate start offset within contexts[] */
4804 : offset_base = 0;
4805 :
4806 0 : for (i = 0; i < (application - (user_list->applications)); i++)
4807 0 : offset_base += user_list->applications[i].num_contexts;
4808 :
4809 0 : for (i = 0; i < application->num_contexts; i++) {
4810 0 : context = &(user_list->contexts[offset_base + i]);
4811 :
4812 0 : if (context) {
4813 0 : old_log_level = context->log_level;
4814 0 : context->log_level = (int8_t)userctxt.log_level; /* No endianess conversion necessary*/
4815 :
4816 0 : old_trace_status = context->trace_status;
4817 0 : context->trace_status = (int8_t)userctxt.trace_status; /* No endianess conversion necessary */
4818 :
4819 : /* The following function sends also the trace status */
4820 0 : if ((context->user_handle >= DLT_FD_MINIMUM)
4821 0 : && (dlt_daemon_user_send_log_level(daemon, context, verbose) != 0)) {
4822 0 : context->log_level = old_log_level;
4823 0 : context->trace_status = old_trace_status;
4824 : }
4825 : }
4826 : }
4827 : }
4828 : }
4829 :
4830 : return DLT_RETURN_OK;
4831 : }
4832 :
4833 0 : int dlt_daemon_process_user_message_log_mode(
4834 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* rec, int verbose)
4835 : {
4836 : DltUserControlMsgLogMode userctxt;
4837 : uint32_t len = sizeof(DltUserControlMsgLogMode);
4838 :
4839 0 : PRINT_FUNCTION_VERBOSE(verbose);
4840 :
4841 0 : if ((daemon == 0) || (daemon_local == 0)) {
4842 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_log_mode()\n");
4843 0 : return -1;
4844 : }
4845 :
4846 : memset(&userctxt, 0, len);
4847 :
4848 0 : if (dlt_receiver_check_and_get(rec, &userctxt, len, DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
4849 : /* Not enough bytes received */
4850 : return -1;
4851 :
4852 : /* set the new log mode */
4853 0 : daemon->mode = userctxt.log_mode;
4854 :
4855 : /* write configuration persistantly */
4856 0 : dlt_daemon_configuration_save(daemon, daemon->runtime_configuration, verbose);
4857 :
4858 0 : return 0;
4859 : }
4860 :
4861 0 : int dlt_daemon_process_user_message_marker(
4862 : DltDaemon* daemon, DltDaemonLocal* daemon_local, DltReceiver* rec, int verbose)
4863 : {
4864 : uint32_t len = sizeof(DltUserControlMsgLogMode);
4865 : DltUserControlMsgLogMode userctxt;
4866 0 : PRINT_FUNCTION_VERBOSE(verbose);
4867 :
4868 0 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
4869 0 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n", __func__);
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 : /* Create automatic unregister context response for unregistered context */
4880 0 : dlt_daemon_control_message_marker(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, verbose);
4881 :
4882 0 : return 0;
4883 : }
4884 :
4885 0 : int dlt_daemon_send_ringbuffer_to_client(DltDaemon* daemon, DltDaemonLocal* daemon_local, int verbose)
4886 : {
4887 : int ret;
4888 : static uint8_t data[DLT_DAEMON_RCVBUFSIZE];
4889 : int length;
4890 :
4891 0 : PRINT_FUNCTION_VERBOSE(verbose);
4892 :
4893 0 : if ((daemon == 0) || (daemon_local == 0)) {
4894 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_send_ringbuffer_to_client()\n");
4895 0 : return DLT_DAEMON_ERROR_UNKNOWN;
4896 : }
4897 :
4898 0 : if (dlt_buffer_get_message_count(&(daemon->client_ringbuffer)) <= 0) {
4899 0 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_DIRECT);
4900 0 : return DLT_DAEMON_ERROR_OK;
4901 : }
4902 :
4903 0 : while ((length = dlt_buffer_copy(&(daemon->client_ringbuffer), data, sizeof(data))) > 0) {
4904 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
4905 : dlt_daemon_trigger_systemd_watchdog_if_necessary(daemon);
4906 : #endif
4907 :
4908 0 : if ((ret = dlt_daemon_client_send(
4909 : DLT_DAEMON_SEND_FORCE, daemon, daemon_local, 0, 0, data, length, 0, 0, verbose)))
4910 0 : return ret;
4911 :
4912 0 : dlt_buffer_remove(&(daemon->client_ringbuffer));
4913 :
4914 0 : if (daemon->state != DLT_DAEMON_STATE_SEND_BUFFER)
4915 0 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_BUFFER);
4916 :
4917 0 : if (dlt_buffer_get_message_count(&(daemon->client_ringbuffer)) <= 0) {
4918 0 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_DIRECT);
4919 0 : return DLT_DAEMON_ERROR_OK;
4920 : }
4921 : }
4922 :
4923 : return DLT_DAEMON_ERROR_OK;
4924 : }
4925 :
4926 0 : int dlt_daemon_send_ringbuffer_to_client_v2(DltDaemon* daemon, DltDaemonLocal* daemon_local, int verbose)
4927 : {
4928 : int ret;
4929 : static uint8_t data[DLT_DAEMON_RCVBUFSIZE];
4930 : int length;
4931 :
4932 0 : PRINT_FUNCTION_VERBOSE(verbose);
4933 :
4934 0 : if ((daemon == 0) || (daemon_local == 0)) {
4935 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_send_ringbuffer_to_client()\n");
4936 0 : return DLT_DAEMON_ERROR_UNKNOWN;
4937 : }
4938 :
4939 0 : if (dlt_buffer_get_message_count(&(daemon->client_ringbuffer)) <= 0) {
4940 0 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_DIRECT);
4941 0 : return DLT_DAEMON_ERROR_OK;
4942 : }
4943 :
4944 0 : while ((length = dlt_buffer_copy(&(daemon->client_ringbuffer), data, sizeof(data))) > 0) {
4945 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
4946 : dlt_daemon_trigger_systemd_watchdog_if_necessary(daemon);
4947 : #endif
4948 :
4949 0 : if ((ret = dlt_daemon_client_send_v2(
4950 : DLT_DAEMON_SEND_FORCE, daemon, daemon_local, 0, 0, data, length, 0, 0, verbose)))
4951 0 : return ret;
4952 :
4953 0 : dlt_buffer_remove(&(daemon->client_ringbuffer));
4954 :
4955 0 : if (daemon->state != DLT_DAEMON_STATE_SEND_BUFFER)
4956 0 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_BUFFER);
4957 :
4958 0 : if (dlt_buffer_get_message_count(&(daemon->client_ringbuffer)) <= 0) {
4959 0 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_DIRECT);
4960 0 : return DLT_DAEMON_ERROR_OK;
4961 : }
4962 : }
4963 :
4964 : return DLT_DAEMON_ERROR_OK;
4965 : }
4966 :
4967 : #ifdef __QNX__
4968 : static void* timer_thread(void* data)
4969 : {
4970 : int pexit = 0;
4971 : unsigned int sleep_ret = 0;
4972 :
4973 : DltDaemonPeriodicData* timer_thread_data = (DltDaemonPeriodicData*)data;
4974 :
4975 : /* Timer will start in starts_in sec*/
4976 : if ((sleep_ret = sleep(timer_thread_data->starts_in))) {
4977 : dlt_vlog(
4978 : LOG_NOTICE,
4979 : "Sleep remains [%u] for starting!"
4980 : "Stop thread of timer [%d]\n",
4981 : sleep_ret, timer_thread_data->timer_id);
4982 : close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]);
4983 : return NULL;
4984 : }
4985 :
4986 : while (1) {
4987 : if ((dlt_timer_pipes[timer_thread_data->timer_id][1] > 0)
4988 : && (0 > write(dlt_timer_pipes[timer_thread_data->timer_id][1], "1", 1))) {
4989 : dlt_vlog(
4990 : LOG_ERR, "Failed to send notification for timer [%s]!\n", dlt_timer_names[timer_thread_data->timer_id]);
4991 : pexit = 1;
4992 : }
4993 :
4994 : if (pexit || g_exit) {
4995 : dlt_vlog(
4996 : LOG_NOTICE,
4997 : "Received signal!"
4998 : "Stop thread of timer [%d]\n",
4999 : timer_thread_data->timer_id);
5000 : close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]);
5001 : return NULL;
5002 : }
5003 :
5004 : if ((sleep_ret = sleep(timer_thread_data->period_sec))) {
5005 : dlt_vlog(
5006 : LOG_NOTICE,
5007 : "Sleep remains [%u] for interval!"
5008 : "Stop thread of timer [%d]\n",
5009 : sleep_ret, timer_thread_data->timer_id);
5010 : close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]);
5011 : return NULL;
5012 : }
5013 : }
5014 : }
5015 : #endif
5016 :
5017 1 : int create_timer_fd(DltDaemonLocal* daemon_local, unsigned int period_sec, unsigned int starts_in, DltTimers timer_id)
5018 : {
5019 : int local_fd = DLT_FD_INIT;
5020 : char* timer_name = NULL;
5021 :
5022 1 : if (timer_id >= DLT_TIMER_UNKNOWN) {
5023 0 : dlt_log(DLT_LOG_ERROR, "Unknown timer.");
5024 0 : return -1;
5025 : }
5026 :
5027 1 : timer_name = dlt_timer_names[timer_id];
5028 :
5029 1 : if (daemon_local == NULL) {
5030 0 : dlt_log(DLT_LOG_ERROR, "Daemon local structure is NULL");
5031 0 : return -1;
5032 : }
5033 :
5034 1 : if ((period_sec == 0) || (starts_in == 0)) {
5035 : /* timer not activated via the service file */
5036 0 : dlt_vlog(LOG_INFO, "<%s> not set: period=0\n", timer_name);
5037 : local_fd = DLT_FD_INIT;
5038 : } else {
5039 : #ifdef linux
5040 : struct itimerspec l_timer_spec;
5041 1 : local_fd = timerfd_create(CLOCK_MONOTONIC, 0);
5042 :
5043 1 : if (local_fd < 0)
5044 0 : dlt_vlog(LOG_WARNING, "<%s> timerfd_create failed: %s\n", timer_name, strerror(errno));
5045 :
5046 1 : l_timer_spec.it_interval.tv_sec = (long int)period_sec;
5047 1 : l_timer_spec.it_interval.tv_nsec = (long int)0;
5048 1 : l_timer_spec.it_value.tv_sec = (long int)starts_in;
5049 1 : l_timer_spec.it_value.tv_nsec = (long int)0;
5050 :
5051 1 : if (timerfd_settime(local_fd, 0, &l_timer_spec, NULL) < 0) {
5052 0 : dlt_vlog(LOG_WARNING, "<%s> timerfd_settime failed: %s\n", timer_name, strerror(errno));
5053 : local_fd = DLT_FD_INIT;
5054 : }
5055 : #elif defined(__QNX__)
5056 : /*
5057 : * Since timerfd is not valid in QNX, new threads are introduced
5058 : * to manage timers and communicate with main thread when timer expires.
5059 : */
5060 : if (0 != pipe(dlt_timer_pipes[timer_id])) {
5061 : dlt_vlog(LOG_ERR, "Failed to create pipe for timer [%s]", dlt_timer_names[timer_id]);
5062 : return -1;
5063 : }
5064 : if (NULL == timer_data[timer_id]) {
5065 : timer_data[timer_id] = calloc(1, sizeof(DltDaemonPeriodicData));
5066 : if (NULL == timer_data[timer_id]) {
5067 : dlt_vlog(LOG_ERR, "Failed to allocate memory for timer_data [%s]!\n", dlt_timer_names[timer_id]);
5068 : close_pipes(dlt_timer_pipes[timer_id]);
5069 : return -1;
5070 : }
5071 : }
5072 :
5073 : timer_data[timer_id]->timer_id = timer_id;
5074 : timer_data[timer_id]->period_sec = period_sec;
5075 : timer_data[timer_id]->starts_in = starts_in;
5076 : timer_data[timer_id]->wakeups_missed = 0;
5077 :
5078 : if (0 != pthread_create(&timer_threads[timer_id], NULL, &timer_thread, (void*)timer_data[timer_id])) {
5079 : dlt_vlog(LOG_ERR, "Failed to create new thread for timer [%s]!\n", dlt_timer_names[timer_id]);
5080 : /* Clean up timer before returning */
5081 : close_pipes(dlt_timer_pipes[timer_id]);
5082 : free(timer_data[timer_id]);
5083 : timer_data[timer_id] = NULL;
5084 :
5085 : return -1;
5086 : }
5087 : local_fd = dlt_timer_pipes[timer_id][0];
5088 : #endif
5089 : }
5090 :
5091 1 : return dlt_connection_create(daemon_local, &daemon_local->pEvent, local_fd, POLLIN, dlt_timer_conn_types[timer_id]);
5092 : }
5093 :
5094 : /* Close connection function */
5095 1 : int dlt_daemon_close_socket(int sock, DltDaemon* daemon, DltDaemonLocal* daemon_local, int verbose)
5096 : {
5097 1 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = {'\0'};
5098 :
5099 1 : PRINT_FUNCTION_VERBOSE(verbose);
5100 :
5101 1 : if ((daemon_local == NULL) || (daemon == NULL)) {
5102 0 : dlt_log(LOG_ERR, "dlt_daemon_close_socket: Invalid input parmeters\n");
5103 0 : return -1;
5104 : }
5105 :
5106 : /* Closure is done while unregistering has for any connection */
5107 1 : dlt_event_handler_unregister_connection(&daemon_local->pEvent, daemon_local, sock);
5108 :
5109 1 : if (daemon_local->client_connections == 0) {
5110 : /* send new log state to all applications */
5111 1 : daemon->connectionState = 0;
5112 :
5113 1 : if (daemon->daemon_version == DLTProtocolV2) {
5114 0 : dlt_daemon_user_send_all_log_state_v2(daemon, verbose);
5115 1 : } else if (daemon->daemon_version == DLTProtocolV1) {
5116 1 : dlt_daemon_user_send_all_log_state(daemon, verbose);
5117 : } else {
5118 0 : dlt_vlog(LOG_ERR, "Unsupported DLT version %u in %s\n", daemon->daemon_version, __func__);
5119 0 : return -1;
5120 : }
5121 :
5122 : /* For offline tracing we still can use the same states */
5123 : /* as for socket sending. Using this trick we see the traces */
5124 : /* In the offline trace AND in the socket stream. */
5125 1 : if (daemon_local->flags.yvalue[0] == 0)
5126 1 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_BUFFER);
5127 : }
5128 :
5129 1 : if (daemon->daemon_version == DLTProtocolV2) {
5130 0 : dlt_daemon_control_message_connection_info_v2(
5131 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, DLT_CONNECTION_STATUS_DISCONNECTED, "", verbose);
5132 1 : } else if (daemon->daemon_version == DLTProtocolV1) {
5133 1 : dlt_daemon_control_message_connection_info(
5134 : DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, DLT_CONNECTION_STATUS_DISCONNECTED, "", verbose);
5135 : } else {
5136 0 : dlt_vlog(LOG_ERR, "Unsupported DLT version %u in %s\n", daemon->daemon_version, __func__);
5137 0 : return -1;
5138 : }
5139 :
5140 1 : snprintf(
5141 : local_str, DLT_DAEMON_TEXTBUFSIZE, "Client connection #%d closed. Total Clients : %d", sock,
5142 : daemon_local->client_connections);
5143 1 : dlt_daemon_log_internal(
5144 : daemon, daemon_local, local_str, DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID, daemon_local->flags.vflag);
5145 1 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
5146 :
5147 1 : return 0;
5148 : }
5149 :
5150 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
5151 :
5152 : static DltReturnValue dlt_daemon_output_internal_msg(
5153 : const DltLogLevelType loglevel, const char* const text, void* const params)
5154 : {
5155 : struct DltTraceLoadLogParams* log_params = (struct DltTraceLoadLogParams*)params;
5156 : return dlt_daemon_log_internal(
5157 : log_params->daemon, log_params->daemon_local, (char*)text, loglevel, log_params->app_id,
5158 : DLT_TRACE_LOAD_CONTEXT_ID, log_params->verbose);
5159 : }
5160 : #endif
5161 :
5162 :
5163 : /**
5164 : \}
5165 : */
|