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