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