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 1496 : while ((back >= 0) && (g_exit >= 0))
1619 1487 : 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_t)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 : size_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 : (size_t)lineSize >= (fieldNameLen + 1) &&
2293 0 : strchr(kDelimiters, line[fieldNameLen]) != NULL) {
2294 : /* trim fieldName */
2295 : line += fieldNameLen;
2296 :
2297 : /* trim delimiter */
2298 0 : ++line;
2299 :
2300 : /* trim leading delimiters */
2301 0 : while (*line != '\0' && strchr(kDelimiters, *line) != NULL) {
2302 0 : ++line;
2303 : --lineSize;
2304 : }
2305 :
2306 0 : result = strdup(line);
2307 0 : break;
2308 : }
2309 : }
2310 :
2311 0 : free(buffer);
2312 :
2313 0 : return result;
2314 : }
2315 :
2316 9 : int dlt_daemon_local_ecu_version_init(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
2317 : {
2318 : FILE *f = NULL;
2319 :
2320 9 : PRINT_FUNCTION_VERBOSE(verbose);
2321 :
2322 : /* By default, version string is null. */
2323 9 : daemon->ECUVersionString = NULL;
2324 :
2325 : /* Open the file. Bail out if error occurs */
2326 9 : f = fopen(daemon_local->flags.pathToECUSoftwareVersion, "r");
2327 :
2328 9 : if (f == NULL) {
2329 : /* Error level notice, because this might be deliberate choice */
2330 9 : dlt_log(LOG_NOTICE, "Failed to open ECU Software version file.\n");
2331 9 : return -1;
2332 : }
2333 :
2334 0 : if (daemon_local->flags.ecuSoftwareVersionFileField[0] != '\0') {
2335 0 : daemon->ECUVersionString = file_read_field(f, daemon_local->flags.ecuSoftwareVersionFileField);
2336 : } else {
2337 0 : daemon->ECUVersionString = file_read_everything(f, DLT_DAEMON_TEXTBUFSIZE);
2338 : }
2339 :
2340 0 : fclose(f);
2341 :
2342 0 : return (daemon->ECUVersionString != NULL) ? 0 : -1;
2343 : }
2344 :
2345 9 : void dlt_daemon_local_cleanup(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
2346 : {
2347 9 : PRINT_FUNCTION_VERBOSE(verbose);
2348 :
2349 9 : if ((daemon == 0) || (daemon_local == 0)) {
2350 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_cleanup()\n");
2351 0 : return;
2352 : }
2353 :
2354 : /* Don't receive event anymore */
2355 9 : dlt_event_handler_cleanup_connections(&daemon_local->pEvent);
2356 :
2357 9 : dlt_message_free(&(daemon_local->msg), daemon_local->flags.vflag);
2358 :
2359 : /* free shared memory */
2360 9 : if (daemon_local->flags.offlineTraceDirectory[0])
2361 0 : multiple_files_buffer_free(&(daemon_local->offlineTrace));
2362 :
2363 : /* Ignore result */
2364 9 : dlt_file_free(&(daemon_local->file), daemon_local->flags.vflag);
2365 :
2366 : #ifdef DLT_DAEMON_USE_FIFO_IPC
2367 : /* Try to delete existing pipe, ignore result of unlink() */
2368 9 : unlink(daemon_local->flags.daemonFifoName);
2369 : #else /* DLT_DAEMON_USE_UNIX_SOCKET_IPC */
2370 : /* Try to delete existing pipe, ignore result of unlink() */
2371 : if (unlink(daemon_local->flags.appSockPath) != 0) {
2372 : dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n",
2373 : __func__, strerror(errno));
2374 : }
2375 : #endif
2376 :
2377 : #ifdef DLT_SHM_ENABLE
2378 : /* free shared memory */
2379 : dlt_shm_free_server(&(daemon_local->dlt_shm), daemon_local->flags.dltShmName);
2380 : free(daemon_local->recv_buf_shm);
2381 : daemon_local->recv_buf_shm = NULL;
2382 : #endif
2383 :
2384 9 : if (daemon_local->flags.offlineLogstorageMaxDevices > 0) {
2385 : /* disconnect all logstorage devices */
2386 6 : dlt_daemon_logstorage_cleanup(daemon,
2387 : daemon_local,
2388 : daemon_local->flags.vflag);
2389 :
2390 6 : free(daemon->storage_handle);
2391 : }
2392 :
2393 9 : if (daemon->ECUVersionString != NULL)
2394 9 : free(daemon->ECUVersionString);
2395 :
2396 9 : if (unlink(daemon_local->flags.ctrlSockPath) != 0) {
2397 1 : dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n",
2398 1 : __func__, strerror(errno));
2399 : }
2400 :
2401 : /* free IP list */
2402 9 : free(daemon_local->flags.ipNodes);
2403 : }
2404 :
2405 9 : void dlt_daemon_exit_trigger()
2406 : {
2407 : /* stop event loop */
2408 9 : g_exit = -1;
2409 :
2410 : #ifdef DLT_DAEMON_USE_FIFO_IPC
2411 9 : char tmp[DLT_PATH_MAX] = { 0 };
2412 :
2413 : ssize_t n;
2414 9 : n = snprintf(tmp, DLT_PATH_MAX, "%s/dlt", dltFifoBaseDir);
2415 9 : if (n < 0 || (size_t)n > DLT_PATH_MAX) {
2416 0 : dlt_vlog(LOG_WARNING, "%s: snprintf truncation/error(%ld) %s\n",
2417 : __func__, n, tmp);
2418 : }
2419 :
2420 9 : (void)unlink(tmp);
2421 : #endif
2422 :
2423 : #ifdef __QNX__
2424 : dlt_daemon_cleanup_timers();
2425 : #endif
2426 :
2427 9 : }
2428 :
2429 9 : void dlt_daemon_signal_handler(int sig)
2430 : {
2431 9 : g_signo = sig;
2432 :
2433 9 : switch (sig) {
2434 9 : case SIGHUP:
2435 : case SIGTERM:
2436 : case SIGINT:
2437 : case SIGQUIT:
2438 : {
2439 : /* finalize the server */
2440 9 : dlt_vlog(LOG_NOTICE, "Exiting DLT daemon due to signal: %s\n",
2441 : strsignal(sig));
2442 9 : dlt_daemon_exit_trigger();
2443 9 : break;
2444 : }
2445 : default:
2446 : {
2447 : /* This case should never happen! */
2448 : break;
2449 : }
2450 : } /* switch */
2451 :
2452 9 : } /* dlt_daemon_signal_handler() */
2453 :
2454 : #ifdef __QNX__
2455 : void dlt_daemon_cleanup_timers()
2456 : {
2457 : int i = 0;
2458 : while (i < DLT_TIMER_UNKNOWN) {
2459 : /* Remove FIFO of every timer and kill timer thread */
2460 : if (0 != timer_threads[i]) {
2461 : pthread_kill(timer_threads[i], SIGUSR1);
2462 : pthread_join(timer_threads[i], NULL);
2463 : timer_threads[i] = 0;
2464 :
2465 : close_pipes(dlt_timer_pipes[i]);
2466 :
2467 : /* Free data of every timer */
2468 : if (NULL != timer_data[i]) {
2469 : free(timer_data[i]);
2470 : timer_data[i] = NULL;
2471 : }
2472 : }
2473 : i++;
2474 : }
2475 : }
2476 : #endif
2477 :
2478 2 : void dlt_daemon_daemonize(int verbose)
2479 : {
2480 : int i;
2481 : int fd;
2482 :
2483 2 : PRINT_FUNCTION_VERBOSE(verbose);
2484 :
2485 2 : dlt_log(LOG_NOTICE, "Daemon mode\n");
2486 :
2487 : /* Daemonize */
2488 2 : i = fork();
2489 :
2490 4 : if (i < 0) {
2491 0 : dlt_log(LOG_CRIT, "Unable to fork(), exiting DLT daemon\n");
2492 0 : exit(-1); /* fork error */
2493 : }
2494 :
2495 4 : if (i > 0)
2496 2 : exit(0); /* parent exits */
2497 :
2498 : /* child (daemon) continues */
2499 :
2500 : /* Process independency */
2501 :
2502 : /* obtain a new process group */
2503 2 : if (setsid() == -1) {
2504 0 : dlt_log(LOG_CRIT, "setsid() failed, exiting DLT daemon\n");
2505 0 : exit(-1); /* fork error */
2506 : }
2507 :
2508 : /* Open standard descriptors stdin, stdout, stderr */
2509 : fd = open("/dev/null", O_RDWR);
2510 :
2511 2 : if (fd != -1) {
2512 : /* Redirect STDOUT to /dev/null */
2513 2 : if (dup2(fd, STDOUT_FILENO) < 0)
2514 0 : dlt_vlog(LOG_WARNING, "Failed to direct stdout to /dev/null. Error: %s\n", strerror(errno));
2515 :
2516 : /* Redirect STDERR to /dev/null */
2517 2 : if (dup2(fd, STDERR_FILENO) < 0)
2518 0 : dlt_vlog(LOG_WARNING, "Failed to direct stderr to /dev/null. Error: %s\n", strerror(errno));
2519 :
2520 2 : close(fd);
2521 : }
2522 : else {
2523 0 : dlt_log(LOG_CRIT, "Error opening /dev/null, exiting DLT daemon\n");
2524 0 : exit(-1); /* fork error */
2525 : }
2526 :
2527 : /* Set umask */
2528 2 : umask(DLT_DAEMON_UMASK);
2529 :
2530 : /* Change to root directory */
2531 2 : if (chdir("/") < 0)
2532 0 : dlt_log(LOG_WARNING, "Failed to chdir to root\n");
2533 :
2534 : /* Catch signals */
2535 2 : signal(SIGCHLD, SIG_IGN); /* ignore child */
2536 2 : signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
2537 2 : signal(SIGTTOU, SIG_IGN);
2538 2 : signal(SIGTTIN, SIG_IGN);
2539 :
2540 2 : } /* dlt_daemon_daemonize() */
2541 :
2542 : /* This function logs str to the configured output sink (socket, serial, offline trace).
2543 : * To avoid recursion this function must be called only from DLT highlevel functions.
2544 : * E. g. calling it to output a failure when the open of the offline trace file fails
2545 : * would cause an endless loop because dlt_daemon_log_internal() would itself again try
2546 : * to open the offline trace file.
2547 : * This is a dlt-daemon only function. The libdlt has no equivalent function available. */
2548 40 : int dlt_daemon_log_internal(DltDaemon *daemon, DltDaemonLocal *daemon_local,
2549 : char *str, DltLogLevelType level,
2550 : const char *app_id, const char *ctx_id, int verbose)
2551 : {
2552 40 : DltMessage msg = { 0 };
2553 : static uint8_t uiMsgCount = 0;
2554 : DltStandardHeaderExtra *pStandardExtra = NULL;
2555 : uint32_t uiType;
2556 : uint16_t uiSize;
2557 : uint32_t uiExtraSize;
2558 :
2559 40 : PRINT_FUNCTION_VERBOSE(verbose);
2560 :
2561 : /* Set storageheader */
2562 40 : msg.storageheader = (DltStorageHeader *)(msg.headerbuffer);
2563 40 : dlt_set_storageheader(msg.storageheader, daemon->ecuid);
2564 :
2565 : /* Set standardheader */
2566 40 : msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader));
2567 40 : msg.standardheader->htyp = DLT_HTYP_UEH | DLT_HTYP_WEID | DLT_HTYP_WSID | DLT_HTYP_WTMS |
2568 : DLT_HTYP_PROTOCOL_VERSION1;
2569 40 : msg.standardheader->mcnt = uiMsgCount++;
2570 :
2571 : uiExtraSize = (uint32_t) (DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp) +
2572 : (DLT_IS_HTYP_UEH(msg.standardheader->htyp) ? sizeof(DltExtendedHeader) : 0));
2573 40 : msg.headersize = (uint32_t) sizeof(DltStorageHeader) + (uint32_t) sizeof(DltStandardHeader) + uiExtraSize;
2574 :
2575 : /* Set extraheader */
2576 : pStandardExtra =
2577 : (DltStandardHeaderExtra *)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader));
2578 40 : dlt_set_id(pStandardExtra->ecu, daemon->ecuid);
2579 40 : pStandardExtra->tmsp = DLT_HTOBE_32(dlt_uptime());
2580 40 : pStandardExtra->seid = (unsigned int) DLT_HTOBE_32(getpid());
2581 :
2582 : /* Set extendedheader */
2583 40 : msg.extendedheader =
2584 40 : (DltExtendedHeader *)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) +
2585 40 : DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp));
2586 40 : msg.extendedheader->msin = DLT_MSIN_VERB | (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) |
2587 40 : ((level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN);
2588 40 : msg.extendedheader->noar = 1;
2589 40 : dlt_set_id(msg.extendedheader->apid, app_id);
2590 40 : dlt_set_id(msg.extendedheader->ctid, ctx_id);
2591 :
2592 : /* Set payload data... */
2593 40 : uiType = DLT_TYPE_INFO_STRG;
2594 40 : uiSize = (uint16_t) (strlen(str) + 1);
2595 40 : msg.datasize = (uint32_t) (sizeof(uint32_t) + sizeof(uint16_t) + uiSize);
2596 :
2597 40 : msg.databuffer = (uint8_t *)malloc((size_t) msg.datasize);
2598 40 : msg.databuffersize = msg.datasize;
2599 :
2600 40 : if (msg.databuffer == 0) {
2601 0 : dlt_log(LOG_WARNING, "Can't allocate buffer for get log info message\n");
2602 0 : return -1;
2603 : }
2604 :
2605 : msg.datasize = 0;
2606 : memcpy((uint8_t *)(msg.databuffer + msg.datasize), (uint8_t *)(&uiType), sizeof(uint32_t));
2607 40 : msg.datasize += (uint32_t) sizeof(uint32_t);
2608 40 : memcpy((uint8_t *)(msg.databuffer + msg.datasize), (uint8_t *)(&uiSize), sizeof(uint16_t));
2609 40 : msg.datasize += (uint32_t) sizeof(uint16_t);
2610 40 : memcpy((uint8_t *)(msg.databuffer + msg.datasize), str, uiSize);
2611 40 : msg.datasize += uiSize;
2612 :
2613 : /* Calc length */
2614 40 : msg.standardheader->len = DLT_HTOBE_16(msg.headersize - sizeof(DltStorageHeader) + msg.datasize);
2615 :
2616 40 : dlt_daemon_client_send(DLT_DAEMON_SEND_TO_ALL, daemon,daemon_local,
2617 : msg.headerbuffer, sizeof(DltStorageHeader),
2618 : msg.headerbuffer + sizeof(DltStorageHeader),
2619 40 : (int) (msg.headersize - sizeof(DltStorageHeader)),
2620 40 : msg.databuffer, (int) msg.datasize, verbose);
2621 :
2622 40 : free(msg.databuffer);
2623 :
2624 40 : return 0;
2625 : }
2626 :
2627 3 : int dlt_daemon_check_numeric_setting(char *token,
2628 : char *value,
2629 : unsigned long *data)
2630 3 : {
2631 3 : char value_check[value_length];
2632 3 : value_check[0] = 0;
2633 3 : sscanf(value, "%lu%s", data, value_check);
2634 3 : if (value_check[0] || !isdigit(value[0])) {
2635 0 : fprintf(stderr, "Invalid input [%s] detected in option %s\n",
2636 : value,
2637 : token);
2638 0 : return -1;
2639 : }
2640 : return 0;
2641 : }
2642 :
2643 4 : int dlt_daemon_process_client_connect(DltDaemon *daemon,
2644 : DltDaemonLocal *daemon_local,
2645 : DltReceiver *receiver,
2646 : int verbose)
2647 : {
2648 : socklen_t cli_size;
2649 : struct sockaddr_un cli;
2650 :
2651 : int in_sock = -1;
2652 4 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
2653 :
2654 4 : PRINT_FUNCTION_VERBOSE(verbose);
2655 :
2656 4 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
2657 0 : dlt_log(LOG_ERR,
2658 : "Invalid function parameters used for function "
2659 : "dlt_daemon_process_client_connect()\n");
2660 0 : return -1;
2661 : }
2662 :
2663 : /* event from TCP server socket, new connection */
2664 4 : cli_size = sizeof(cli);
2665 :
2666 4 : if ((in_sock = accept(receiver->fd, (struct sockaddr *)&cli, &cli_size)) < 0) {
2667 0 : if (errno == ECONNABORTED) // Caused by nmap -v -p 3490 -Pn <IP of dlt-daemon>
2668 : return 0;
2669 0 : dlt_vlog(LOG_ERR, "accept() for socket %d failed: %s\n", receiver->fd, strerror(errno));
2670 0 : return -1;
2671 : }
2672 :
2673 : /* check if file file descriptor was already used, and make it invalid if it
2674 : * is reused. */
2675 : /* This prevents sending messages to wrong file descriptor */
2676 4 : dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
2677 4 : dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
2678 :
2679 : /* Set socket timeout in reception */
2680 : struct timeval timeout_send;
2681 4 : timeout_send.tv_sec = daemon_local->timeoutOnSend;
2682 4 : timeout_send.tv_usec = 0;
2683 :
2684 4 : if (setsockopt (in_sock,
2685 : SOL_SOCKET,
2686 : SO_SNDTIMEO,
2687 : (char *)&timeout_send,
2688 : sizeof(timeout_send)) < 0)
2689 0 : dlt_log(LOG_WARNING, "setsockopt failed\n");
2690 :
2691 4 : if (dlt_connection_create(daemon_local,
2692 : &daemon_local->pEvent,
2693 : in_sock,
2694 : POLLIN,
2695 : DLT_CONNECTION_CLIENT_MSG_TCP)) {
2696 0 : dlt_log(LOG_ERR, "Failed to register new client. \n");
2697 0 : close(in_sock);
2698 0 : return -1;
2699 : }
2700 :
2701 : /* send connection info about connected */
2702 4 : dlt_daemon_control_message_connection_info(in_sock,
2703 : daemon,
2704 : daemon_local,
2705 : DLT_CONNECTION_STATUS_CONNECTED,
2706 : "",
2707 : verbose);
2708 :
2709 : /* send ecu version string */
2710 4 : if (daemon_local->flags.sendECUSoftwareVersion > 0) {
2711 : if (daemon_local->flags.sendECUSoftwareVersion > 0)
2712 0 : dlt_daemon_control_get_software_version(DLT_DAEMON_SEND_TO_ALL,
2713 : daemon,
2714 : daemon_local,
2715 : daemon_local->flags.vflag);
2716 :
2717 0 : if (daemon_local->flags.sendTimezone > 0)
2718 0 : dlt_daemon_control_message_timezone(DLT_DAEMON_SEND_TO_ALL,
2719 : daemon,
2720 : daemon_local,
2721 : daemon_local->flags.vflag);
2722 : }
2723 :
2724 4 : snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE,
2725 : "New client connection #%d established, Total Clients : %d",
2726 : in_sock, daemon_local->client_connections);
2727 :
2728 4 : dlt_daemon_log_internal(daemon, daemon_local, local_str, DLT_LOG_INFO,
2729 : DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
2730 : daemon_local->flags.vflag);
2731 4 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
2732 :
2733 4 : if (daemon_local->client_connections == 1) {
2734 2 : if (daemon_local->flags.vflag)
2735 0 : dlt_log(LOG_DEBUG, "Send ring-buffer to client\n");
2736 :
2737 2 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_BUFFER);
2738 :
2739 2 : if (dlt_daemon_send_ringbuffer_to_client(daemon, daemon_local, verbose) == -1) {
2740 0 : dlt_log(LOG_WARNING, "Can't send contents of ringbuffer to clients\n");
2741 0 : close(in_sock);
2742 : in_sock = -1;
2743 0 : return -1;
2744 : }
2745 :
2746 : /* send new log state to all applications */
2747 2 : daemon->connectionState = 1;
2748 2 : dlt_daemon_user_send_all_log_state(daemon, verbose);
2749 :
2750 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
2751 : /* Reset number of received bytes from FIFO */
2752 : daemon->bytes_recv = 0;
2753 : #endif
2754 : }
2755 :
2756 : return 0;
2757 : }
2758 :
2759 9 : int dlt_daemon_process_client_messages(DltDaemon *daemon,
2760 : DltDaemonLocal *daemon_local,
2761 : DltReceiver *receiver,
2762 : int verbose)
2763 : {
2764 : int bytes_to_be_removed = 0;
2765 : int must_close_socket = -1;
2766 :
2767 9 : PRINT_FUNCTION_VERBOSE(verbose);
2768 :
2769 9 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
2770 0 : dlt_log(LOG_ERR,
2771 : "Invalid function parameters used for function "
2772 : "dlt_daemon_process_client_messages()\n");
2773 0 : return -1;
2774 : }
2775 :
2776 9 : must_close_socket = dlt_receiver_receive(receiver);
2777 :
2778 9 : if (must_close_socket < 0) {
2779 0 : dlt_daemon_close_socket(receiver->fd,
2780 : daemon,
2781 : daemon_local,
2782 : verbose);
2783 0 : return -1;
2784 : }
2785 :
2786 : /* Process all received messages */
2787 19 : while (dlt_message_read(&(daemon_local->msg),
2788 19 : (uint8_t *)receiver->buf,
2789 19 : (unsigned int) receiver->bytesRcvd,
2790 : daemon_local->flags.nflag,
2791 19 : daemon_local->flags.vflag) == DLT_MESSAGE_ERROR_OK) {
2792 : /* Check for control message */
2793 10 : if ((0 < receiver->fd) &&
2794 10 : DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg)))
2795 10 : dlt_daemon_client_process_control(receiver->fd,
2796 : daemon,
2797 : daemon_local,
2798 : &(daemon_local->msg),
2799 : daemon_local->flags.vflag);
2800 :
2801 10 : bytes_to_be_removed = (int) (daemon_local->msg.headersize +
2802 10 : daemon_local->msg.datasize -
2803 : sizeof(DltStorageHeader));
2804 :
2805 10 : if (daemon_local->msg.found_serialheader)
2806 : bytes_to_be_removed += (int) sizeof(dltSerialHeader);
2807 :
2808 10 : if (daemon_local->msg.resync_offset)
2809 0 : bytes_to_be_removed += daemon_local->msg.resync_offset;
2810 :
2811 10 : if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) {
2812 0 : dlt_log(LOG_WARNING,
2813 : "Can't remove bytes from receiver for sockets\n");
2814 0 : return -1;
2815 : }
2816 : } /* while */
2817 :
2818 9 : if (dlt_receiver_move_to_begin(receiver) == -1) {
2819 0 : dlt_log(LOG_WARNING,
2820 : "Can't move bytes to beginning of receiver buffer for sockets\n");
2821 0 : return -1;
2822 : }
2823 :
2824 9 : if (must_close_socket == 0)
2825 : /* FIXME: Why the hell do we need to close the socket
2826 : * on control message reception ??
2827 : */
2828 2 : dlt_daemon_close_socket(receiver->fd,
2829 : daemon,
2830 : daemon_local,
2831 : verbose);
2832 :
2833 : return 0;
2834 : }
2835 :
2836 0 : int dlt_daemon_process_client_messages_serial(DltDaemon *daemon,
2837 : DltDaemonLocal *daemon_local,
2838 : DltReceiver *receiver,
2839 : int verbose)
2840 : {
2841 : int bytes_to_be_removed = 0;
2842 :
2843 0 : PRINT_FUNCTION_VERBOSE(verbose);
2844 :
2845 0 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
2846 0 : dlt_log(LOG_ERR,
2847 : "Invalid function parameters used for function "
2848 : "dlt_daemon_process_client_messages_serial()\n");
2849 0 : return -1;
2850 : }
2851 :
2852 0 : if (dlt_receiver_receive(receiver) <= 0) {
2853 0 : dlt_log(LOG_WARNING,
2854 : "dlt_receiver_receive_fd() for messages from serial interface "
2855 : "failed!\n");
2856 0 : return -1;
2857 : }
2858 :
2859 : /* Process all received messages */
2860 0 : while (dlt_message_read(&(daemon_local->msg),
2861 0 : (uint8_t *)receiver->buf,
2862 0 : (unsigned int) receiver->bytesRcvd,
2863 : daemon_local->flags.mflag,
2864 0 : daemon_local->flags.vflag) == DLT_MESSAGE_ERROR_OK) {
2865 : /* Check for control message */
2866 0 : if (DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg))) {
2867 0 : if (dlt_daemon_client_process_control(receiver->fd,
2868 : daemon,
2869 : daemon_local,
2870 : &(daemon_local->msg),
2871 : daemon_local->flags.vflag)
2872 : == -1) {
2873 0 : dlt_log(LOG_WARNING, "Can't process control messages\n");
2874 0 : return -1;
2875 : }
2876 : }
2877 :
2878 0 : bytes_to_be_removed = (int) (daemon_local->msg.headersize +
2879 0 : daemon_local->msg.datasize -
2880 : sizeof(DltStorageHeader));
2881 :
2882 0 : if (daemon_local->msg.found_serialheader)
2883 : bytes_to_be_removed += (int) sizeof(dltSerialHeader);
2884 :
2885 0 : if (daemon_local->msg.resync_offset)
2886 0 : bytes_to_be_removed += daemon_local->msg.resync_offset;
2887 :
2888 0 : if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) {
2889 0 : dlt_log(LOG_WARNING,
2890 : "Can't remove bytes from receiver for serial connection\n");
2891 0 : return -1;
2892 : }
2893 : } /* while */
2894 :
2895 0 : if (dlt_receiver_move_to_begin(receiver) == -1) {
2896 0 : dlt_log(LOG_WARNING,
2897 : "Can't move bytes to beginning of receiver buffer for serial "
2898 : "connection\n");
2899 0 : return -1;
2900 : }
2901 :
2902 : return 0;
2903 : }
2904 :
2905 2 : int dlt_daemon_process_control_connect(
2906 : DltDaemon *daemon,
2907 : DltDaemonLocal *daemon_local,
2908 : DltReceiver *receiver,
2909 : int verbose)
2910 : {
2911 : socklen_t ctrl_size;
2912 : struct sockaddr_un ctrl;
2913 : int in_sock = -1;
2914 :
2915 2 : PRINT_FUNCTION_VERBOSE(verbose);
2916 :
2917 2 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
2918 0 : dlt_log(LOG_ERR,
2919 : "Invalid function parameters used for function "
2920 : "dlt_daemon_process_control_connect()\n");
2921 0 : return -1;
2922 : }
2923 :
2924 : /* event from UNIX server socket, new connection */
2925 2 : ctrl_size = sizeof(ctrl);
2926 :
2927 2 : if ((in_sock = accept(receiver->fd, (struct sockaddr *)&ctrl, &ctrl_size)) < 0) {
2928 0 : dlt_vlog(LOG_ERR, "accept() on UNIX control socket %d failed: %s\n", receiver->fd, strerror(errno));
2929 0 : return -1;
2930 : }
2931 :
2932 : /* check if file file descriptor was already used, and make it invalid if it
2933 : * is reused */
2934 : /* This prevents sending messages to wrong file descriptor */
2935 2 : dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
2936 2 : dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
2937 :
2938 2 : if (dlt_connection_create(daemon_local,
2939 : &daemon_local->pEvent,
2940 : in_sock,
2941 : POLLIN,
2942 : DLT_CONNECTION_CONTROL_MSG)) {
2943 0 : dlt_log(LOG_ERR, "Failed to register new client. \n");
2944 : /* TODO: Perform clean-up */
2945 0 : return -1;
2946 : }
2947 :
2948 2 : if (verbose)
2949 0 : dlt_vlog(LOG_INFO, "New connection to control client established\n");
2950 :
2951 : return 0;
2952 : }
2953 :
2954 : #if defined DLT_DAEMON_USE_UNIX_SOCKET_IPC || defined DLT_DAEMON_VSOCK_IPC_ENABLE
2955 : int dlt_daemon_process_app_connect(
2956 : DltDaemon *daemon,
2957 : DltDaemonLocal *daemon_local,
2958 : DltReceiver *receiver,
2959 : int verbose)
2960 : {
2961 : int in_sock = -1;
2962 :
2963 : PRINT_FUNCTION_VERBOSE(verbose);
2964 :
2965 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
2966 : dlt_vlog(LOG_ERR,
2967 : "%s: Invalid parameters\n",
2968 : __func__);
2969 : return DLT_RETURN_WRONG_PARAMETER;
2970 : }
2971 :
2972 : /* event from server socket, new connection */
2973 :
2974 : if ((in_sock = accept(receiver->fd, NULL, NULL)) < 0) {
2975 : dlt_vlog(LOG_ERR, "accept() on UNIX socket %d failed: %s\n", receiver->fd, strerror(errno));
2976 : return -1;
2977 : }
2978 :
2979 : /* check if file file descriptor was already used, and make it invalid if it
2980 : * is reused. This prevents sending messages to wrong file descriptor */
2981 : dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
2982 : dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
2983 :
2984 : if (dlt_connection_create(daemon_local,
2985 : &daemon_local->pEvent,
2986 : in_sock,
2987 : POLLIN,
2988 : DLT_CONNECTION_APP_MSG)) {
2989 : dlt_log(LOG_ERR, "Failed to register new application. \n");
2990 : close(in_sock);
2991 : return -1;
2992 : }
2993 :
2994 : if (verbose)
2995 : dlt_vlog(LOG_INFO, "New connection to application established\n");
2996 :
2997 : return 0;
2998 : }
2999 : #endif
3000 :
3001 4 : int dlt_daemon_process_control_messages(
3002 : DltDaemon *daemon,
3003 : DltDaemonLocal *daemon_local,
3004 : DltReceiver *receiver,
3005 : int verbose)
3006 : {
3007 : int bytes_to_be_removed = 0;
3008 :
3009 4 : PRINT_FUNCTION_VERBOSE(verbose);
3010 :
3011 4 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
3012 0 : dlt_log(LOG_ERR,
3013 : "Invalid function parameters used for function "
3014 : "dlt_daemon_process_control_messages()\n");
3015 0 : return -1;
3016 : }
3017 :
3018 4 : if (dlt_receiver_receive(receiver) <= 0) {
3019 2 : dlt_daemon_close_socket(receiver->fd,
3020 : daemon,
3021 : daemon_local,
3022 : verbose);
3023 : /* FIXME: Why the hell do we need to close the socket
3024 : * on control message reception ??
3025 : */
3026 2 : return 0;
3027 : }
3028 :
3029 : /* Process all received messages */
3030 4 : while (dlt_message_read(
3031 : &(daemon_local->msg),
3032 4 : (uint8_t *)receiver->buf,
3033 4 : (unsigned int) receiver->bytesRcvd,
3034 : daemon_local->flags.nflag,
3035 4 : daemon_local->flags.vflag) == DLT_MESSAGE_ERROR_OK) {
3036 : /* Check for control message */
3037 2 : if ((receiver->fd > 0) &&
3038 2 : DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg)))
3039 2 : dlt_daemon_client_process_control(receiver->fd,
3040 : daemon, daemon_local,
3041 : &(daemon_local->msg),
3042 : daemon_local->flags.vflag);
3043 :
3044 2 : bytes_to_be_removed = (int) (daemon_local->msg.headersize +
3045 2 : daemon_local->msg.datasize -
3046 : sizeof(DltStorageHeader));
3047 :
3048 2 : if (daemon_local->msg.found_serialheader)
3049 : bytes_to_be_removed += (int) sizeof(dltSerialHeader);
3050 :
3051 2 : if (daemon_local->msg.resync_offset)
3052 0 : bytes_to_be_removed += daemon_local->msg.resync_offset;
3053 :
3054 2 : if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) {
3055 0 : dlt_log(LOG_WARNING,
3056 : "Can't remove bytes from receiver for sockets\n");
3057 0 : return -1;
3058 : }
3059 : } /* while */
3060 :
3061 2 : if (dlt_receiver_move_to_begin(receiver) == -1) {
3062 0 : dlt_log(LOG_WARNING, "Can't move bytes to beginning of receiver buffer for sockets\n");
3063 0 : return -1;
3064 : }
3065 :
3066 : return 0;
3067 : }
3068 :
3069 0 : static int dlt_daemon_process_user_message_not_sup(DltDaemon *daemon,
3070 : DltDaemonLocal *daemon_local,
3071 : DltReceiver *receiver,
3072 : int verbose)
3073 : {
3074 0 : DltUserHeader *userheader = (DltUserHeader *)(receiver->buf);
3075 : (void)daemon;
3076 : (void)daemon_local;
3077 :
3078 0 : PRINT_FUNCTION_VERBOSE(verbose);
3079 :
3080 0 : dlt_vlog(LOG_ERR, "Invalid user message type received: %u!\n",
3081 : userheader->message);
3082 :
3083 : /* remove user header */
3084 0 : if (dlt_receiver_remove(receiver, sizeof(DltUserHeader)) == -1)
3085 0 : dlt_log(LOG_WARNING,
3086 : "Can't remove bytes from receiver for user messages\n");
3087 :
3088 0 : return -1;
3089 : }
3090 :
3091 : static dlt_daemon_process_user_message_func process_user_func[DLT_USER_MESSAGE_NOT_SUPPORTED] = {
3092 : dlt_daemon_process_user_message_not_sup,
3093 : dlt_daemon_process_user_message_log,
3094 : dlt_daemon_process_user_message_register_application,
3095 : dlt_daemon_process_user_message_unregister_application,
3096 : dlt_daemon_process_user_message_register_context,
3097 : dlt_daemon_process_user_message_unregister_context,
3098 : dlt_daemon_process_user_message_not_sup,
3099 : dlt_daemon_process_user_message_not_sup,
3100 : dlt_daemon_process_user_message_overflow,
3101 : dlt_daemon_process_user_message_set_app_ll_ts,
3102 : dlt_daemon_process_user_message_not_sup,
3103 : dlt_daemon_process_user_message_not_sup,
3104 : dlt_daemon_process_user_message_not_sup,
3105 : dlt_daemon_process_user_message_marker,
3106 : dlt_daemon_process_user_message_not_sup,
3107 : dlt_daemon_process_user_message_not_sup
3108 : };
3109 :
3110 1447 : int dlt_daemon_process_user_messages(DltDaemon *daemon,
3111 : DltDaemonLocal *daemon_local,
3112 : DltReceiver *receiver,
3113 : int verbose)
3114 : {
3115 : int offset = 0;
3116 : int run_loop = 1;
3117 : int32_t min_size = (int32_t) sizeof(DltUserHeader);
3118 : DltUserHeader *userheader;
3119 : int recv;
3120 :
3121 1447 : PRINT_FUNCTION_VERBOSE(verbose);
3122 :
3123 1447 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
3124 0 : dlt_log(LOG_ERR,
3125 : "Invalid function parameters used for function "
3126 : "dlt_daemon_process_user_messages()\n");
3127 0 : return -1;
3128 : }
3129 :
3130 1447 : recv = dlt_receiver_receive(receiver);
3131 :
3132 1447 : if (recv <= 0 && receiver->type == DLT_RECEIVE_SOCKET) {
3133 0 : dlt_daemon_close_socket(receiver->fd,
3134 : daemon,
3135 : daemon_local,
3136 : verbose);
3137 0 : return 0;
3138 : }
3139 1447 : else if (recv < 0) {
3140 0 : dlt_log(LOG_WARNING,
3141 : "dlt_receiver_receive_fd() for user messages failed!\n");
3142 0 : return -1;
3143 : }
3144 :
3145 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
3146 : /* Count up number of received bytes from FIFO */
3147 : if (receiver->bytesRcvd > receiver->lastBytesRcvd)
3148 : {
3149 : daemon->bytes_recv += receiver->bytesRcvd - receiver->lastBytesRcvd;
3150 : }
3151 : #endif
3152 :
3153 : /* look through buffer as long as data is in there */
3154 7344 : while ((receiver->bytesRcvd >= min_size) && run_loop) {
3155 : dlt_daemon_process_user_message_func func = NULL;
3156 :
3157 : offset = 0;
3158 5897 : userheader = (DltUserHeader *)(receiver->buf + offset);
3159 :
3160 5897 : while (!dlt_user_check_userheader(userheader) &&
3161 0 : (offset + min_size <= receiver->bytesRcvd)) {
3162 : /* resync if necessary */
3163 0 : offset++;
3164 0 : userheader = (DltUserHeader *)(receiver->buf + offset);
3165 : }
3166 :
3167 : /* Check for user header pattern */
3168 5897 : if (!dlt_user_check_userheader(userheader))
3169 : break;
3170 :
3171 : /* Set new start offset */
3172 5897 : if (offset > 0) {
3173 0 : if (dlt_receiver_remove(receiver, offset) == -1) {
3174 0 : dlt_log(LOG_WARNING,
3175 : "Can't remove offset from receiver\n");
3176 0 : return -1;
3177 : }
3178 : }
3179 :
3180 5897 : if (userheader->message >= DLT_USER_MESSAGE_NOT_SUPPORTED)
3181 : func = dlt_daemon_process_user_message_not_sup;
3182 : else
3183 5897 : func = process_user_func[userheader->message];
3184 :
3185 5897 : if (func(daemon,
3186 : daemon_local,
3187 : receiver,
3188 : daemon_local->flags.vflag) == -1)
3189 : run_loop = 0;
3190 : }
3191 :
3192 : /* keep not read data in buffer */
3193 1447 : if (dlt_receiver_move_to_begin(receiver) == -1) {
3194 0 : dlt_log(LOG_WARNING,
3195 : "Can't move bytes to beginning of receiver buffer for user "
3196 : "messages\n");
3197 0 : return -1;
3198 : }
3199 :
3200 : return 0;
3201 : }
3202 :
3203 0 : int dlt_daemon_process_user_message_overflow(DltDaemon *daemon,
3204 : DltDaemonLocal *daemon_local,
3205 : DltReceiver *rec,
3206 : int verbose)
3207 : {
3208 : uint32_t len = sizeof(DltUserControlMsgBufferOverflow);
3209 : DltUserControlMsgBufferOverflow userpayload;
3210 :
3211 0 : PRINT_FUNCTION_VERBOSE(verbose);
3212 :
3213 0 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
3214 0 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n",
3215 : __func__);
3216 0 : return -1;
3217 : }
3218 :
3219 0 : if (dlt_receiver_check_and_get(rec,
3220 : &userpayload,
3221 : len,
3222 : DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
3223 : /* Not enough bytes received */
3224 : return -1;
3225 :
3226 : /* Store in daemon, that a message buffer overflow has occured */
3227 : /* look if TCP connection to client is available or it least message can be put into buffer */
3228 0 : if (dlt_daemon_control_message_buffer_overflow(DLT_DAEMON_SEND_TO_ALL,
3229 : daemon,
3230 : daemon_local,
3231 : userpayload.overflow_counter,
3232 : userpayload.apid,
3233 : verbose))
3234 : /* there was an error when storing message */
3235 : /* add the counter of lost messages to the daemon counter */
3236 0 : daemon->overflow_counter += userpayload.overflow_counter;
3237 :
3238 : return 0;
3239 : }
3240 :
3241 0 : int dlt_daemon_send_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
3242 : {
3243 : int ret;
3244 0 : PRINT_FUNCTION_VERBOSE(verbose);
3245 :
3246 0 : if ((daemon == 0) || (daemon_local == 0)) {
3247 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_overflow()\n");
3248 0 : return DLT_DAEMON_ERROR_UNKNOWN;
3249 : }
3250 :
3251 : /* Store in daemon, that a message buffer overflow has occured */
3252 0 : if ((ret =
3253 0 : dlt_daemon_control_message_buffer_overflow(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local,
3254 : daemon->overflow_counter,
3255 : "", verbose)))
3256 0 : return ret;
3257 :
3258 : return DLT_DAEMON_ERROR_OK;
3259 : }
3260 :
3261 7 : int dlt_daemon_process_user_message_register_application(DltDaemon *daemon,
3262 : DltDaemonLocal *daemon_local,
3263 : DltReceiver *rec,
3264 : int verbose)
3265 : {
3266 : uint32_t len = sizeof(DltUserControlMsgRegisterApplication);
3267 : uint32_t to_remove = 0;
3268 : DltDaemonApplication *application = NULL;
3269 : DltDaemonApplication *old_application = NULL;
3270 : pid_t old_pid = 0;
3271 7 : char description[DLT_DAEMON_DESCSIZE + 1] = { '\0' };
3272 : DltUserControlMsgRegisterApplication userapp;
3273 : char *origin;
3274 : int fd = -1;
3275 :
3276 7 : PRINT_FUNCTION_VERBOSE(verbose);
3277 :
3278 7 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
3279 0 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n",
3280 : __func__);
3281 0 : return -1;
3282 : }
3283 :
3284 : memset(&userapp, 0, sizeof(DltUserControlMsgRegisterApplication));
3285 7 : origin = rec->buf;
3286 :
3287 : /* Adding temp variable to check the return value */
3288 : int temp = 0;
3289 :
3290 : /* We shall not remove data before checking that everything is there. */
3291 7 : temp = dlt_receiver_check_and_get(rec,
3292 : &userapp,
3293 : len,
3294 : DLT_RCV_SKIP_HEADER);
3295 :
3296 7 : if (temp < 0)
3297 : /* Not enough bytes received */
3298 : return -1;
3299 : else {
3300 7 : to_remove = (uint32_t) temp;
3301 : }
3302 :
3303 7 : len = userapp.description_length;
3304 :
3305 7 : if (len > DLT_DAEMON_DESCSIZE) {
3306 : len = DLT_DAEMON_DESCSIZE;
3307 0 : dlt_log(LOG_WARNING, "Application description exceeds limit\n");
3308 : }
3309 :
3310 : /* adjust buffer pointer */
3311 7 : rec->buf += to_remove + sizeof(DltUserHeader);
3312 :
3313 7 : if (dlt_receiver_check_and_get(rec, description, len, DLT_RCV_NONE) < 0) {
3314 0 : dlt_log(LOG_ERR, "Unable to get application description\n");
3315 : /* in case description was not readable, set dummy description */
3316 : memcpy(description, "Unknown", sizeof("Unknown"));
3317 :
3318 : /* unknown len of original description, set to 0 to not remove in next
3319 : * step. Because message buffer is re-adjusted the corrupted description
3320 : * is ignored. */
3321 : len = 0;
3322 : }
3323 :
3324 : /* adjust to_remove */
3325 7 : to_remove += (uint32_t) sizeof(DltUserHeader) + len;
3326 : /* point to begin of message */
3327 7 : rec->buf = origin;
3328 :
3329 : /* We can now remove data. */
3330 7 : if (dlt_receiver_remove(rec, (int) to_remove) != DLT_RETURN_OK) {
3331 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n");
3332 0 : return -1;
3333 : }
3334 :
3335 7 : old_application = dlt_daemon_application_find(daemon, userapp.apid, daemon->ecuid, verbose);
3336 :
3337 7 : if (old_application != NULL)
3338 0 : old_pid = old_application->pid;
3339 :
3340 7 : if (rec->type == DLT_RECEIVE_SOCKET)
3341 0 : fd = rec->fd; /* For sockets, an app specific fd has already been created with accept(). */
3342 :
3343 7 : application = dlt_daemon_application_add(daemon,
3344 : userapp.apid,
3345 : userapp.pid,
3346 : description,
3347 : fd,
3348 : daemon->ecuid,
3349 : verbose);
3350 :
3351 : /* send log state to new application */
3352 7 : dlt_daemon_user_send_log_state(daemon, application, verbose);
3353 :
3354 7 : if (application == NULL) {
3355 0 : dlt_vlog(LOG_WARNING, "Can't add ApplicationID '%.4s' for PID %d\n",
3356 : userapp.apid, userapp.pid);
3357 0 : return -1;
3358 : }
3359 7 : else if (old_pid != application->pid)
3360 : {
3361 7 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
3362 :
3363 7 : snprintf(local_str,
3364 : DLT_DAEMON_TEXTBUFSIZE,
3365 : "ApplicationID '%.4s' registered for PID %d, Description=%s",
3366 7 : application->apid,
3367 : application->pid,
3368 : application->application_description);
3369 7 : dlt_daemon_log_internal(daemon, daemon_local, local_str, DLT_LOG_INFO,
3370 : DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
3371 : daemon_local->flags.vflag);
3372 7 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
3373 : }
3374 :
3375 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
3376 : if (dlt_daemon_user_send_trace_load_config(daemon, application, verbose) != DLT_RETURN_OK)
3377 : dlt_vlog(LOG_WARNING, "Cannot send trace config to Apid: %.4s, PID: %d\n",
3378 : application->apid, application->pid);
3379 : #endif
3380 :
3381 : return 0;
3382 : }
3383 :
3384 38 : int dlt_daemon_process_user_message_register_context(DltDaemon *daemon,
3385 : DltDaemonLocal *daemon_local,
3386 : DltReceiver *rec,
3387 : int verbose)
3388 : {
3389 : uint32_t to_remove = 0;
3390 : uint32_t len = sizeof(DltUserControlMsgRegisterContext);
3391 : DltUserControlMsgRegisterContext userctxt;
3392 38 : char description[DLT_DAEMON_DESCSIZE + 1] = { '\0' };
3393 : DltDaemonApplication *application = NULL;
3394 : DltDaemonContext *context = NULL;
3395 : DltServiceGetLogInfoRequest *req = NULL;
3396 : char *origin;
3397 :
3398 : DltMessage msg;
3399 :
3400 38 : PRINT_FUNCTION_VERBOSE(verbose);
3401 :
3402 38 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
3403 0 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n",
3404 : __func__);
3405 0 : return -1;
3406 : }
3407 :
3408 : memset(&userctxt, 0, sizeof(DltUserControlMsgRegisterContext));
3409 38 : origin = rec->buf;
3410 :
3411 : /* Adding temp variable to check the return value */
3412 : int temp = 0;
3413 :
3414 38 : temp = dlt_receiver_check_and_get(rec,
3415 : &userctxt,
3416 : len,
3417 : DLT_RCV_SKIP_HEADER);
3418 :
3419 38 : if (temp < 0)
3420 : /* Not enough bytes received */
3421 : return -1;
3422 : else {
3423 38 : to_remove = (uint32_t) temp;
3424 : }
3425 :
3426 38 : len = userctxt.description_length;
3427 :
3428 38 : if (len > DLT_DAEMON_DESCSIZE) {
3429 0 : dlt_vlog(LOG_WARNING, "Context description exceeds limit: %u\n", len);
3430 : len = DLT_DAEMON_DESCSIZE;
3431 : }
3432 :
3433 : /* adjust buffer pointer */
3434 38 : rec->buf += to_remove + sizeof(DltUserHeader);
3435 :
3436 38 : if (dlt_receiver_check_and_get(rec, description, len, DLT_RCV_NONE) < 0) {
3437 0 : dlt_log(LOG_ERR, "Unable to get context description\n");
3438 : /* in case description was not readable, set dummy description */
3439 : memcpy(description, "Unknown", sizeof("Unknown"));
3440 :
3441 : /* unknown len of original description, set to 0 to not remove in next
3442 : * step. Because message buffer is re-adjusted the corrupted description
3443 : * is ignored. */
3444 : len = 0;
3445 : }
3446 :
3447 : /* adjust to_remove */
3448 38 : to_remove += (uint32_t) sizeof(DltUserHeader) + len;
3449 : /* point to begin of message */
3450 38 : rec->buf = origin;
3451 :
3452 : /* We can now remove data. */
3453 38 : if (dlt_receiver_remove(rec, (int) to_remove) != DLT_RETURN_OK) {
3454 0 : dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n");
3455 0 : return -1;
3456 : }
3457 :
3458 38 : application = dlt_daemon_application_find(daemon,
3459 : userctxt.apid,
3460 38 : daemon->ecuid,
3461 : verbose);
3462 :
3463 38 : if (application == 0) {
3464 0 : dlt_vlog(LOG_WARNING,
3465 : "ApID '%.4s' not found for new ContextID '%.4s' in %s\n",
3466 : userctxt.apid,
3467 : userctxt.ctid,
3468 : __func__);
3469 :
3470 0 : return 0;
3471 : }
3472 :
3473 : /* Set log level */
3474 38 : if (userctxt.log_level == DLT_USER_LOG_LEVEL_NOT_SET) {
3475 38 : userctxt.log_level = DLT_LOG_DEFAULT;
3476 : } else {
3477 : /* Plausibility check */
3478 0 : if ((userctxt.log_level < DLT_LOG_DEFAULT) ||
3479 : (userctxt.log_level > DLT_LOG_VERBOSE)) {
3480 : return -1;
3481 : }
3482 : }
3483 :
3484 : /* Set trace status */
3485 38 : if (userctxt.trace_status == DLT_USER_TRACE_STATUS_NOT_SET) {
3486 38 : userctxt.trace_status = DLT_TRACE_STATUS_DEFAULT;
3487 : } else {
3488 : /* Plausibility check */
3489 0 : if ((userctxt.trace_status < DLT_TRACE_STATUS_DEFAULT) ||
3490 : (userctxt.trace_status > DLT_TRACE_STATUS_ON)) {
3491 : return -1;
3492 : }
3493 : }
3494 :
3495 38 : context = dlt_daemon_context_add(daemon,
3496 : userctxt.apid,
3497 : userctxt.ctid,
3498 38 : userctxt.log_level,
3499 38 : userctxt.trace_status,
3500 : userctxt.log_level_pos,
3501 : application->user_handle,
3502 : description,
3503 : daemon->ecuid,
3504 : verbose);
3505 :
3506 38 : if (context == 0) {
3507 0 : dlt_vlog(LOG_WARNING,
3508 : "Can't add ContextID '%.4s' for ApID '%.4s'\n in %s",
3509 : userctxt.ctid, userctxt.apid, __func__);
3510 0 : return -1;
3511 : }
3512 : else {
3513 38 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
3514 :
3515 38 : snprintf(local_str,
3516 : DLT_DAEMON_TEXTBUFSIZE,
3517 : "ContextID '%.4s' registered for ApID '%.4s', Description=%s",
3518 38 : context->ctid,
3519 38 : context->apid,
3520 : context->context_description);
3521 :
3522 38 : if (verbose)
3523 0 : dlt_daemon_log_internal(daemon, daemon_local, local_str,
3524 : DLT_LOG_INFO, DLT_DAEMON_APP_ID,
3525 : DLT_DAEMON_CTX_ID, verbose);
3526 :
3527 38 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
3528 : }
3529 :
3530 38 : if (daemon_local->flags.offlineLogstorageMaxDevices)
3531 : /* Store log level set for offline logstorage into context structure*/
3532 33 : context->storage_log_level =
3533 33 : (int8_t) dlt_daemon_logstorage_get_loglevel(daemon,
3534 33 : (int8_t) daemon_local->flags.offlineLogstorageMaxDevices,
3535 : userctxt.apid,
3536 : userctxt.ctid);
3537 : else
3538 5 : context->storage_log_level = DLT_LOG_DEFAULT;
3539 :
3540 : /* Create automatic get log info response for registered context */
3541 38 : if (daemon_local->flags.rflag) {
3542 : /* Prepare request for get log info with one application and one context */
3543 0 : if (dlt_message_init(&msg, verbose) == -1) {
3544 0 : dlt_log(LOG_WARNING, "Can't initialize message");
3545 0 : return -1;
3546 : }
3547 :
3548 0 : msg.datasize = sizeof(DltServiceGetLogInfoRequest);
3549 :
3550 0 : if (msg.databuffer && (msg.databuffersize < msg.datasize)) {
3551 0 : free(msg.databuffer);
3552 0 : msg.databuffer = 0;
3553 : }
3554 :
3555 0 : if (msg.databuffer == 0) {
3556 0 : msg.databuffer = (uint8_t *)malloc(msg.datasize);
3557 0 : msg.databuffersize = msg.datasize;
3558 : }
3559 :
3560 0 : if (msg.databuffer == 0) {
3561 0 : dlt_log(LOG_WARNING, "Can't allocate buffer for get log info message\n");
3562 0 : return -1;
3563 : }
3564 :
3565 : req = (DltServiceGetLogInfoRequest *)msg.databuffer;
3566 :
3567 0 : req->service_id = DLT_SERVICE_ID_GET_LOG_INFO;
3568 0 : req->options = (uint8_t) daemon_local->flags.autoResponseGetLogInfoOption;
3569 0 : dlt_set_id(req->apid, userctxt.apid);
3570 0 : dlt_set_id(req->ctid, userctxt.ctid);
3571 0 : dlt_set_id(req->com, "remo");
3572 :
3573 0 : dlt_daemon_control_get_log_info(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, &msg, verbose);
3574 :
3575 0 : dlt_message_free(&msg, verbose);
3576 : }
3577 :
3578 38 : if (context->user_handle >= DLT_FD_MINIMUM) {
3579 38 : if ((userctxt.log_level == DLT_LOG_DEFAULT) || (userctxt.trace_status == DLT_TRACE_STATUS_DEFAULT)) {
3580 : /* This call also replaces the default values with the values defined for default */
3581 38 : if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) {
3582 0 : dlt_vlog(LOG_WARNING, "Can't send current log level as response to %s for (%.4s;%.4s)\n",
3583 : __func__,
3584 : context->apid,
3585 : context->ctid);
3586 0 : return -1;
3587 : }
3588 : }
3589 : }
3590 :
3591 : return 0;
3592 : }
3593 :
3594 6 : int dlt_daemon_process_user_message_unregister_application(DltDaemon *daemon,
3595 : DltDaemonLocal *daemon_local,
3596 : DltReceiver *rec,
3597 : int verbose)
3598 : {
3599 : uint32_t len = sizeof(DltUserControlMsgUnregisterApplication);
3600 : DltUserControlMsgUnregisterApplication userapp;
3601 : DltDaemonApplication *application = NULL;
3602 : DltDaemonContext *context;
3603 : int i, offset_base;
3604 : DltDaemonRegisteredUsers *user_list = NULL;
3605 :
3606 6 : PRINT_FUNCTION_VERBOSE(verbose);
3607 :
3608 6 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
3609 0 : dlt_vlog(LOG_ERR,
3610 : "Invalid function parameters used for %s\n",
3611 : __func__);
3612 0 : return -1;
3613 : }
3614 :
3615 6 : if (dlt_receiver_check_and_get(rec,
3616 : &userapp,
3617 : len,
3618 : DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
3619 : /* Not enough bytes received */
3620 : return -1;
3621 :
3622 6 : user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
3623 :
3624 6 : if (user_list == NULL)
3625 : return -1;
3626 :
3627 6 : if (user_list->num_applications > 0) {
3628 : /* Delete this application and all corresponding contexts
3629 : * for this application from internal table.
3630 : */
3631 6 : application = dlt_daemon_application_find(daemon,
3632 : userapp.apid,
3633 : daemon->ecuid,
3634 : verbose);
3635 :
3636 6 : if (application) {
3637 : /* Calculate start offset within contexts[] */
3638 : offset_base = 0;
3639 :
3640 6 : for (i = 0; i < (application - (user_list->applications)); i++)
3641 0 : offset_base += user_list->applications[i].num_contexts;
3642 :
3643 6 : for (i = (application->num_contexts) - 1; i >= 0; i--) {
3644 0 : context = &(user_list->contexts[offset_base + i]);
3645 :
3646 0 : if (context) {
3647 : /* Delete context */
3648 0 : if (dlt_daemon_context_del(daemon,
3649 : context,
3650 : daemon->ecuid,
3651 : verbose) == -1) {
3652 0 : dlt_vlog(LOG_WARNING,
3653 : "Can't delete CtID '%.4s' for ApID '%.4s' in %s\n",
3654 0 : context->ctid,
3655 0 : context->apid,
3656 : __func__);
3657 0 : return -1;
3658 : }
3659 : }
3660 : }
3661 :
3662 : /* Delete this application entry from internal table*/
3663 6 : if (dlt_daemon_application_del(daemon,
3664 : application,
3665 : daemon->ecuid,
3666 : verbose) == -1) {
3667 0 : dlt_vlog(LOG_WARNING,
3668 : "Can't delete ApID '%.4s' in %s\n",
3669 0 : application->apid,
3670 : __func__);
3671 0 : return -1;
3672 : }
3673 : else {
3674 6 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
3675 :
3676 : snprintf(local_str,
3677 : DLT_DAEMON_TEXTBUFSIZE,
3678 : "Unregistered ApID '%.4s'",
3679 : userapp.apid);
3680 6 : dlt_daemon_log_internal(daemon, daemon_local, local_str,
3681 : DLT_LOG_INFO, DLT_DAEMON_APP_ID,
3682 : DLT_DAEMON_CTX_ID, verbose);
3683 6 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
3684 : }
3685 : }
3686 : }
3687 :
3688 : return 0;
3689 : }
3690 :
3691 37 : int dlt_daemon_process_user_message_unregister_context(DltDaemon *daemon,
3692 : DltDaemonLocal *daemon_local,
3693 : DltReceiver *rec,
3694 : int verbose)
3695 : {
3696 : uint32_t len = sizeof(DltUserControlMsgUnregisterContext);
3697 : DltUserControlMsgUnregisterContext userctxt;
3698 : DltDaemonContext *context;
3699 :
3700 37 : PRINT_FUNCTION_VERBOSE(verbose);
3701 :
3702 37 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
3703 0 : dlt_vlog(LOG_ERR,
3704 : "Invalid function parameters used for %s\n",
3705 : __func__);
3706 :
3707 0 : return -1;
3708 : }
3709 :
3710 37 : if (dlt_receiver_check_and_get(rec,
3711 : &userctxt,
3712 : len,
3713 : DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
3714 : /* Not enough bytes received */
3715 : return -1;
3716 :
3717 37 : context = dlt_daemon_context_find(daemon,
3718 : userctxt.apid,
3719 : userctxt.ctid,
3720 37 : daemon->ecuid,
3721 : verbose);
3722 :
3723 : /* In case the daemon is loaded with predefined contexts and its context
3724 : * unregisters, the context information will not be deleted from daemon's
3725 : * table until its parent application is unregistered.
3726 : */
3727 37 : if (context && (context->predefined == false)) {
3728 : /* Delete this connection entry from internal table*/
3729 37 : if (dlt_daemon_context_del(daemon, context, daemon->ecuid, verbose) == -1) {
3730 0 : dlt_vlog(LOG_WARNING,
3731 : "Can't delete CtID '%.4s' for ApID '%.4s' in %s\n",
3732 : userctxt.ctid,
3733 : userctxt.apid,
3734 : __func__);
3735 0 : return -1;
3736 : }
3737 : else {
3738 37 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
3739 :
3740 : snprintf(local_str,
3741 : DLT_DAEMON_TEXTBUFSIZE,
3742 : "Unregistered CtID '%.4s' for ApID '%.4s'",
3743 : userctxt.ctid,
3744 : userctxt.apid);
3745 :
3746 37 : if (verbose)
3747 0 : dlt_daemon_log_internal(daemon, daemon_local, local_str,
3748 : DLT_LOG_INFO, DLT_DAEMON_APP_ID,
3749 : DLT_DAEMON_CTX_ID, verbose);
3750 :
3751 37 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
3752 : }
3753 : }
3754 :
3755 : /* Create automatic unregister context response for unregistered context */
3756 37 : if (daemon_local->flags.rflag)
3757 0 : dlt_daemon_control_message_unregister_context(DLT_DAEMON_SEND_TO_ALL,
3758 : daemon,
3759 : daemon_local,
3760 : userctxt.apid,
3761 : userctxt.ctid,
3762 : "remo",
3763 : verbose);
3764 :
3765 : return 0;
3766 : }
3767 :
3768 5809 : int dlt_daemon_process_user_message_log(DltDaemon *daemon,
3769 : DltDaemonLocal *daemon_local,
3770 : DltReceiver *rec,
3771 : int verbose)
3772 : {
3773 : int ret = 0;
3774 : int size = 0;
3775 :
3776 5809 : PRINT_FUNCTION_VERBOSE(verbose);
3777 :
3778 5809 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
3779 0 : dlt_vlog(LOG_ERR, "%s: invalid function parameters.\n", __func__);
3780 0 : return DLT_DAEMON_ERROR_UNKNOWN;
3781 : }
3782 :
3783 : #ifdef DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE
3784 : daemon->received_message_since_last_watchdog_interval = 1;
3785 : #endif
3786 : #ifdef DLT_SHM_ENABLE
3787 :
3788 : /** In case of SHM, the header still received via fifo/unix_socket receiver,
3789 : * so we need to remove header from the receiver.
3790 : */
3791 : if (dlt_receiver_remove(rec, sizeof(DltUserHeader)) < 0)
3792 : /* Not enough bytes received to remove*/
3793 : return DLT_DAEMON_ERROR_UNKNOWN;
3794 :
3795 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
3796 : const unsigned int start_time = dlt_uptime();
3797 : #endif
3798 :
3799 : while (1) {
3800 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
3801 : const unsigned int uptime = dlt_uptime();
3802 : if ((uptime - start_time) / 10000 > daemon->watchdog_trigger_interval) {
3803 : dlt_vlog(LOG_WARNING,
3804 : "spent already 1 watchdog trigger interval in %s, yielding to process other events.\n", __func__);
3805 : if (sd_notify(0, "WATCHDOG=1") < 0)
3806 : dlt_vlog(LOG_CRIT, "Could not reset systemd watchdog from %s\n", __func__);
3807 : break;
3808 : }
3809 : #endif
3810 :
3811 : /* get log message from SHM then store into receiver buffer */
3812 : size = dlt_shm_pull(&(daemon_local->dlt_shm),
3813 : daemon_local->recv_buf_shm,
3814 : DLT_SHM_RCV_BUFFER_SIZE);
3815 :
3816 : if (size <= 0)
3817 : break;
3818 :
3819 : ret = dlt_message_read(&(daemon_local->msg),
3820 : daemon_local->recv_buf_shm, size, 0, verbose);
3821 :
3822 : if (DLT_MESSAGE_ERROR_OK != ret) {
3823 : dlt_shm_remove(&(daemon_local->dlt_shm));
3824 : dlt_log(LOG_WARNING, "failed to read messages from shm.\n");
3825 : return DLT_DAEMON_ERROR_UNKNOWN;
3826 : }
3827 :
3828 : #if defined(DLT_LOG_LEVEL_APP_CONFIG) || defined(DLT_TRACE_LOAD_CTRL_ENABLE)
3829 : DltDaemonApplication *app = dlt_daemon_application_find(
3830 : daemon, daemon_local->msg.extendedheader->apid, daemon->ecuid, verbose);
3831 : #endif
3832 :
3833 : /* discard non-allowed levels if enforcement is on */
3834 : bool keep_message = enforce_context_ll_and_ts_keep_message(
3835 : daemon_local
3836 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
3837 : , app
3838 : #endif
3839 : );
3840 :
3841 : // check trace_load
3842 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
3843 : keep_message &= trace_load_keep_message(app, size, daemon, daemon_local, verbose);
3844 : #endif
3845 :
3846 : if (keep_message)
3847 : dlt_daemon_client_send_message_to_all_client(daemon, daemon_local, verbose);
3848 :
3849 : if (DLT_DAEMON_ERROR_OK != ret)
3850 : dlt_log(LOG_ERR, "failed to send message to client.\n");
3851 : }
3852 :
3853 : #else
3854 5809 : ret = dlt_message_read(&(daemon_local->msg),
3855 5809 : (unsigned char *)rec->buf + sizeof(DltUserHeader),
3856 5809 : (unsigned int) ((unsigned int) rec->bytesRcvd - sizeof(DltUserHeader)),
3857 : 0,
3858 : verbose);
3859 :
3860 5809 : if (ret != DLT_MESSAGE_ERROR_OK) {
3861 0 : if (ret != DLT_MESSAGE_ERROR_SIZE)
3862 : /* This is a normal usecase: The daemon reads the data in 10kb chunks.
3863 : * Thus the last trace in this chunk is probably not complete and will be completed
3864 : * with the next chunk read. This happens always when the FIFO is filled with more than 10kb before
3865 : * the daemon is able to read from the FIFO.
3866 : * Thus the loglevel of this message is set to DEBUG.
3867 : * A cleaner solution would be to check more in detail whether the message is not complete (normal usecase)
3868 : * or the headers are corrupted (error case). */
3869 0 : dlt_log(LOG_DEBUG, "Can't read messages from receiver\n");
3870 :
3871 0 : if (dlt_receiver_remove(rec, rec->bytesRcvd) != DLT_RETURN_OK) {
3872 : /* In certain rare scenarios where only a partial message has been received
3873 : * (Eg: kernel IPC buffer memory being full), we want to discard the message
3874 : * and not broadcast it forward to connected clients. Since the DLT library
3875 : * checks return value of the writev() call against the sent total message
3876 : * length, the partial message will be buffered and retransmitted again.
3877 : * This implicitly ensures that no message loss occurs.
3878 : */
3879 0 : dlt_log(LOG_WARNING, "failed to remove required bytes from receiver.\n");
3880 : }
3881 :
3882 0 : return DLT_DAEMON_ERROR_UNKNOWN;
3883 : }
3884 :
3885 : #if defined(DLT_LOG_LEVEL_APP_CONFIG) || defined(DLT_TRACE_LOAD_CTRL_ENABLE)
3886 : DltDaemonApplication *app = dlt_daemon_application_find(
3887 : daemon, daemon_local->msg.extendedheader->apid, daemon->ecuid, verbose);
3888 : #endif
3889 :
3890 : /* discard non-allowed levels if enforcement is on */
3891 0 : bool keep_message = enforce_context_ll_and_ts_keep_message(
3892 : daemon_local
3893 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
3894 : , app
3895 : #endif
3896 : );
3897 :
3898 : // check trace_load
3899 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
3900 : keep_message &=
3901 : trace_load_keep_message(app, size, daemon, daemon_local, verbose);
3902 : #endif
3903 :
3904 0 : if (keep_message)
3905 5809 : dlt_daemon_client_send_message_to_all_client(daemon, daemon_local, verbose);
3906 :
3907 : /* keep not read data in buffer */
3908 5809 : size = (int) (daemon_local->msg.headersize +
3909 5809 : daemon_local->msg.datasize - sizeof(DltStorageHeader) +
3910 : sizeof(DltUserHeader));
3911 :
3912 5809 : if (daemon_local->msg.found_serialheader)
3913 : size += (int) sizeof(dltSerialHeader);
3914 :
3915 5809 : if (dlt_receiver_remove(rec, size) != DLT_RETURN_OK) {
3916 0 : dlt_log(LOG_WARNING, "failed to remove bytes from receiver.\n");
3917 0 : return DLT_DAEMON_ERROR_UNKNOWN;
3918 : }
3919 :
3920 : #endif
3921 :
3922 : return DLT_DAEMON_ERROR_OK;
3923 : }
3924 :
3925 0 : bool enforce_context_ll_and_ts_keep_message(DltDaemonLocal *daemon_local
3926 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
3927 : , DltDaemonApplication *app
3928 : #endif
3929 : )
3930 : {
3931 5809 : if (!daemon_local->flags.enforceContextLLAndTS ||
3932 0 : !daemon_local->msg.extendedheader) {
3933 : return true;
3934 : }
3935 :
3936 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
3937 : if (app == NULL) {
3938 : return true;
3939 : }
3940 : #endif
3941 :
3942 0 : const int mtin = DLT_GET_MSIN_MTIN(daemon_local->msg.extendedheader->msin);
3943 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
3944 : if (app->num_context_log_level_settings > 0) {
3945 : DltDaemonContextLogSettings *log_settings =
3946 : dlt_daemon_find_app_log_level_config(app, daemon_local->msg.extendedheader->ctid);
3947 :
3948 : if (log_settings != NULL) {
3949 : return mtin <= log_settings->log_level;
3950 : }
3951 : }
3952 : #endif
3953 0 : return mtin <= daemon_local->flags.contextLogLevel;
3954 : }
3955 :
3956 :
3957 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
3958 : bool trace_load_keep_message(DltDaemonApplication *app,
3959 : const int size, DltDaemon *const daemon,
3960 : DltDaemonLocal *const daemon_local,
3961 : int verbose)
3962 : {
3963 : bool keep_message = true;
3964 : if (app == NULL || !daemon_local->msg.extendedheader) {
3965 : return keep_message;
3966 : }
3967 :
3968 : DltMessage* msg = &daemon_local->msg;
3969 : const int mtin = DLT_GET_MSIN_MTIN(msg->extendedheader->msin);
3970 :
3971 : struct DltTraceLoadLogParams params = {
3972 : daemon,
3973 : daemon_local,
3974 : verbose,
3975 : app->apid,
3976 : };
3977 :
3978 : DltTraceLoadSettings *trace_load_settings =
3979 : dlt_find_runtime_trace_load_settings(
3980 : app->trace_load_settings, app->trace_load_settings_count,
3981 : app->apid, msg->extendedheader->ctid);
3982 :
3983 : if (trace_load_settings != NULL) {
3984 : pthread_rwlock_wrlock(&trace_load_rw_lock);
3985 : keep_message = dlt_check_trace_load(
3986 : trace_load_settings, mtin, msg->headerextra.tmsp, size,
3987 : dlt_daemon_output_internal_msg, (void *)(¶ms));
3988 : pthread_rwlock_unlock(&trace_load_rw_lock);
3989 : }
3990 : else {
3991 : dlt_vlog(
3992 : LOG_ERR,
3993 : "Failed to lookup trace load limits for %s, "
3994 : "dropping message, likely app was not registered properly\n",
3995 : app->apid);
3996 : keep_message = false;
3997 : }
3998 :
3999 : return keep_message;
4000 : }
4001 : #endif
4002 :
4003 0 : int dlt_daemon_process_user_message_set_app_ll_ts(DltDaemon *daemon,
4004 : DltDaemonLocal *daemon_local,
4005 : DltReceiver *rec,
4006 : int verbose)
4007 : {
4008 : uint32_t len = sizeof(DltUserControlMsgAppLogLevelTraceStatus);
4009 : DltUserControlMsgAppLogLevelTraceStatus userctxt;
4010 : DltDaemonApplication *application;
4011 : DltDaemonContext *context;
4012 : int i, offset_base;
4013 : int8_t old_log_level, old_trace_status;
4014 : DltDaemonRegisteredUsers *user_list = NULL;
4015 :
4016 0 : PRINT_FUNCTION_VERBOSE(verbose);
4017 :
4018 0 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
4019 0 : dlt_vlog(LOG_ERR,
4020 : "Invalid function parameters used for %s\n",
4021 : __func__);
4022 0 : return DLT_RETURN_ERROR;
4023 : }
4024 :
4025 0 : user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
4026 :
4027 0 : if (user_list == NULL)
4028 : return DLT_RETURN_ERROR;
4029 :
4030 : memset(&userctxt, 0, len);
4031 :
4032 0 : if (dlt_receiver_check_and_get(rec,
4033 : &userctxt,
4034 : len,
4035 : DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
4036 : /* Not enough bytes received */
4037 : return DLT_RETURN_ERROR;
4038 :
4039 0 : if (user_list->num_applications > 0) {
4040 : /* Get all contexts with application id matching the received application id */
4041 0 : application = dlt_daemon_application_find(daemon,
4042 : userctxt.apid,
4043 : daemon->ecuid,
4044 : verbose);
4045 :
4046 0 : if (application) {
4047 : /* Calculate start offset within contexts[] */
4048 : offset_base = 0;
4049 :
4050 0 : for (i = 0; i < (application - (user_list->applications)); i++)
4051 0 : offset_base += user_list->applications[i].num_contexts;
4052 :
4053 0 : for (i = 0; i < application->num_contexts; i++) {
4054 0 : context = &(user_list->contexts[offset_base + i]);
4055 :
4056 0 : if (context) {
4057 0 : old_log_level = context->log_level;
4058 0 : context->log_level = (int8_t) userctxt.log_level; /* No endianess conversion necessary*/
4059 :
4060 0 : old_trace_status = context->trace_status;
4061 0 : context->trace_status = (int8_t) userctxt.trace_status; /* No endianess conversion necessary */
4062 :
4063 : /* The following function sends also the trace status */
4064 0 : if ((context->user_handle >= DLT_FD_MINIMUM) &&
4065 0 : (dlt_daemon_user_send_log_level(daemon,
4066 : context,
4067 : verbose) != 0)) {
4068 0 : context->log_level = old_log_level;
4069 0 : context->trace_status = old_trace_status;
4070 : }
4071 : }
4072 : }
4073 : }
4074 : }
4075 :
4076 : return DLT_RETURN_OK;
4077 : }
4078 :
4079 0 : int dlt_daemon_process_user_message_log_mode(DltDaemon *daemon,
4080 : DltDaemonLocal *daemon_local,
4081 : DltReceiver *rec,
4082 : int verbose)
4083 : {
4084 : DltUserControlMsgLogMode userctxt;
4085 : uint32_t len = sizeof(DltUserControlMsgLogMode);
4086 :
4087 0 : PRINT_FUNCTION_VERBOSE(verbose);
4088 :
4089 0 : if ((daemon == 0) || (daemon_local == 0)) {
4090 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_log_mode()\n");
4091 0 : return -1;
4092 : }
4093 :
4094 : memset(&userctxt, 0, len);
4095 :
4096 0 : if (dlt_receiver_check_and_get(rec,
4097 : &userctxt,
4098 : len,
4099 : DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
4100 : /* Not enough bytes received */
4101 : return -1;
4102 :
4103 : /* set the new log mode */
4104 0 : daemon->mode = userctxt.log_mode;
4105 :
4106 : /* write configuration persistantly */
4107 0 : dlt_daemon_configuration_save(daemon, daemon->runtime_configuration, verbose);
4108 :
4109 0 : return 0;
4110 : }
4111 :
4112 0 : int dlt_daemon_process_user_message_marker(DltDaemon *daemon,
4113 : DltDaemonLocal *daemon_local,
4114 : DltReceiver *rec,
4115 : int verbose)
4116 : {
4117 : uint32_t len = sizeof(DltUserControlMsgLogMode);
4118 : DltUserControlMsgLogMode userctxt;
4119 0 : PRINT_FUNCTION_VERBOSE(verbose);
4120 :
4121 0 : if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
4122 0 : dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n",
4123 : __func__);
4124 0 : return -1;
4125 : }
4126 :
4127 : memset(&userctxt, 0, len);
4128 :
4129 0 : if (dlt_receiver_check_and_get(rec,
4130 : &userctxt,
4131 : len,
4132 : DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
4133 : /* Not enough bytes received */
4134 : return -1;
4135 :
4136 : /* Create automatic unregister context response for unregistered context */
4137 0 : dlt_daemon_control_message_marker(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, verbose);
4138 :
4139 0 : return 0;
4140 : }
4141 :
4142 2 : int dlt_daemon_send_ringbuffer_to_client(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
4143 : {
4144 : int ret;
4145 : static uint8_t data[DLT_DAEMON_RCVBUFSIZE];
4146 : int length;
4147 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
4148 : uint32_t curr_time = 0U;
4149 : #endif
4150 :
4151 2 : PRINT_FUNCTION_VERBOSE(verbose);
4152 :
4153 2 : if ((daemon == 0) || (daemon_local == 0)) {
4154 0 : dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_send_ringbuffer_to_client()\n");
4155 0 : return DLT_DAEMON_ERROR_UNKNOWN;
4156 : }
4157 :
4158 2 : if (dlt_buffer_get_message_count(&(daemon->client_ringbuffer)) <= 0) {
4159 0 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_DIRECT);
4160 0 : return DLT_DAEMON_ERROR_OK;
4161 : }
4162 :
4163 4 : while ((length = dlt_buffer_copy(&(daemon->client_ringbuffer), data, sizeof(data))) > 0) {
4164 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
4165 : dlt_daemon_trigger_systemd_watchdog_if_necessary(&curr_time, daemon->watchdog_trigger_interval);
4166 : #endif
4167 :
4168 4 : if ((ret =
4169 4 : dlt_daemon_client_send(DLT_DAEMON_SEND_FORCE, daemon, daemon_local, 0, 0, data, length, 0, 0,
4170 : verbose)))
4171 0 : return ret;
4172 :
4173 4 : dlt_buffer_remove(&(daemon->client_ringbuffer));
4174 :
4175 4 : if (daemon->state != DLT_DAEMON_STATE_SEND_BUFFER)
4176 0 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_BUFFER);
4177 :
4178 4 : if (dlt_buffer_get_message_count(&(daemon->client_ringbuffer)) <= 0) {
4179 2 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_DIRECT);
4180 2 : return DLT_DAEMON_ERROR_OK;
4181 : }
4182 : }
4183 :
4184 : return DLT_DAEMON_ERROR_OK;
4185 : }
4186 :
4187 : #ifdef __QNX__
4188 : static void *timer_thread(void *data)
4189 : {
4190 : int pexit = 0;
4191 : unsigned int sleep_ret = 0;
4192 :
4193 : DltDaemonPeriodicData* timer_thread_data = (DltDaemonPeriodicData*) data;
4194 :
4195 : /* Timer will start in starts_in sec*/
4196 : if ((sleep_ret = sleep(timer_thread_data->starts_in))) {
4197 : dlt_vlog(LOG_NOTICE, "Sleep remains [%u] for starting!"
4198 : "Stop thread of timer [%d]\n",
4199 : sleep_ret, timer_thread_data->timer_id);
4200 : close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]);
4201 : return NULL;
4202 : }
4203 :
4204 : while (1) {
4205 : if ((dlt_timer_pipes[timer_thread_data->timer_id][1] > 0) &&
4206 : (0 > write(dlt_timer_pipes[timer_thread_data->timer_id][1], "1", 1))) {
4207 : dlt_vlog(LOG_ERR, "Failed to send notification for timer [%s]!\n",
4208 : dlt_timer_names[timer_thread_data->timer_id]);
4209 : pexit = 1;
4210 : }
4211 :
4212 : if (pexit || g_exit) {
4213 : dlt_vlog(LOG_NOTICE, "Received signal!"
4214 : "Stop thread of timer [%d]\n",
4215 : timer_thread_data->timer_id);
4216 : close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]);
4217 : return NULL;
4218 : }
4219 :
4220 : if ((sleep_ret = sleep(timer_thread_data->period_sec))) {
4221 : dlt_vlog(LOG_NOTICE, "Sleep remains [%u] for interval!"
4222 : "Stop thread of timer [%d]\n",
4223 : sleep_ret, timer_thread_data->timer_id);
4224 : close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]);
4225 : return NULL;
4226 : }
4227 : }
4228 : }
4229 : #endif
4230 :
4231 10 : int create_timer_fd(DltDaemonLocal *daemon_local,
4232 : int period_sec,
4233 : int starts_in,
4234 : DltTimers timer_id)
4235 : {
4236 : int local_fd = DLT_FD_INIT;
4237 : char *timer_name = NULL;
4238 :
4239 10 : if (timer_id >= DLT_TIMER_UNKNOWN) {
4240 0 : dlt_log(DLT_LOG_ERROR, "Unknown timer.");
4241 0 : return -1;
4242 : }
4243 :
4244 10 : timer_name = dlt_timer_names[timer_id];
4245 :
4246 10 : if (daemon_local == NULL) {
4247 0 : dlt_log(DLT_LOG_ERROR, "Daemon local structure is NULL");
4248 0 : return -1;
4249 : }
4250 :
4251 10 : if ((period_sec <= 0) || (starts_in <= 0)) {
4252 : /* timer not activated via the service file */
4253 0 : dlt_vlog(LOG_INFO, "<%s> not set: period=0\n", timer_name);
4254 : local_fd = DLT_FD_INIT;
4255 : }
4256 : else {
4257 : #ifdef linux
4258 : struct itimerspec l_timer_spec;
4259 10 : local_fd = timerfd_create(CLOCK_MONOTONIC, 0);
4260 :
4261 10 : if (local_fd < 0)
4262 0 : dlt_vlog(LOG_WARNING, "<%s> timerfd_create failed: %s\n",
4263 0 : timer_name, strerror(errno));
4264 :
4265 10 : l_timer_spec.it_interval.tv_sec = period_sec;
4266 10 : l_timer_spec.it_interval.tv_nsec = 0;
4267 10 : l_timer_spec.it_value.tv_sec = starts_in;
4268 10 : l_timer_spec.it_value.tv_nsec = 0;
4269 :
4270 10 : if (timerfd_settime(local_fd, 0, &l_timer_spec, NULL) < 0) {
4271 0 : dlt_vlog(LOG_WARNING, "<%s> timerfd_settime failed: %s\n",
4272 0 : timer_name, strerror(errno));
4273 : local_fd = DLT_FD_INIT;
4274 : }
4275 : #elif __QNX__
4276 : /*
4277 : * Since timerfd is not valid in QNX, new threads are introduced
4278 : * to manage timers and communicate with main thread when timer expires.
4279 : */
4280 : if(0 != pipe(dlt_timer_pipes[timer_id])) {
4281 : dlt_vlog(LOG_ERR, "Failed to create pipe for timer [%s]",
4282 : dlt_timer_names[timer_id]);
4283 : return -1;
4284 : }
4285 : if (NULL == timer_data[timer_id]) {
4286 : timer_data[timer_id] = calloc(1, sizeof(DltDaemonPeriodicData));
4287 : if (NULL == timer_data[timer_id]) {
4288 : dlt_vlog(LOG_ERR, "Failed to allocate memory for timer_data [%s]!\n",
4289 : dlt_timer_names[timer_id]);
4290 : close_pipes(dlt_timer_pipes[timer_id]);
4291 : return -1;
4292 : }
4293 : }
4294 :
4295 : timer_data[timer_id]->timer_id = timer_id;
4296 : timer_data[timer_id]->period_sec = period_sec;
4297 : timer_data[timer_id]->starts_in = starts_in;
4298 : timer_data[timer_id]->wakeups_missed = 0;
4299 :
4300 : if (0 != pthread_create(&timer_threads[timer_id], NULL,
4301 : &timer_thread, (void*)timer_data[timer_id])) {
4302 : dlt_vlog(LOG_ERR, "Failed to create new thread for timer [%s]!\n",
4303 : dlt_timer_names[timer_id]);
4304 : /* Clean up timer before returning */
4305 : close_pipes(dlt_timer_pipes[timer_id]);
4306 : free(timer_data[timer_id]);
4307 : timer_data[timer_id] = NULL;
4308 :
4309 : return -1;
4310 : }
4311 : local_fd = dlt_timer_pipes[timer_id][0];
4312 : #endif
4313 : }
4314 :
4315 10 : return dlt_connection_create(daemon_local,
4316 : &daemon_local->pEvent,
4317 : local_fd,
4318 : POLLIN,
4319 10 : dlt_timer_conn_types[timer_id]);
4320 : }
4321 :
4322 : /* Close connection function */
4323 5 : int dlt_daemon_close_socket(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
4324 : {
4325 5 : char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
4326 :
4327 5 : PRINT_FUNCTION_VERBOSE(verbose);
4328 :
4329 5 : if ((daemon_local == NULL) || (daemon == NULL)) {
4330 0 : dlt_log(LOG_ERR, "dlt_daemon_close_socket: Invalid input parmeters\n");
4331 0 : return -1;
4332 : }
4333 :
4334 : /* Closure is done while unregistering has for any connection */
4335 5 : dlt_event_handler_unregister_connection(&daemon_local->pEvent,
4336 : daemon_local,
4337 : sock);
4338 :
4339 5 : if (daemon_local->client_connections == 0) {
4340 : /* send new log state to all applications */
4341 3 : daemon->connectionState = 0;
4342 3 : dlt_daemon_user_send_all_log_state(daemon, verbose);
4343 :
4344 : /* For offline tracing we still can use the same states */
4345 : /* as for socket sending. Using this trick we see the traces */
4346 : /* In the offline trace AND in the socket stream. */
4347 3 : if (daemon_local->flags.yvalue[0] == 0)
4348 3 : dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_BUFFER);
4349 : }
4350 :
4351 5 : dlt_daemon_control_message_connection_info(DLT_DAEMON_SEND_TO_ALL,
4352 : daemon,
4353 : daemon_local,
4354 : DLT_CONNECTION_STATUS_DISCONNECTED,
4355 : "",
4356 : verbose);
4357 :
4358 5 : snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE,
4359 : "Client connection #%d closed. Total Clients : %d",
4360 : sock,
4361 : daemon_local->client_connections);
4362 5 : dlt_daemon_log_internal(daemon, daemon_local, local_str, DLT_LOG_INFO,
4363 : DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
4364 : daemon_local->flags.vflag);
4365 5 : dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
4366 :
4367 5 : return 0;
4368 : }
4369 :
4370 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
4371 :
4372 : static DltReturnValue dlt_daemon_output_internal_msg(
4373 : const DltLogLevelType loglevel, const char *const text, void* const params) {
4374 : struct DltTraceLoadLogParams* log_params = (struct DltTraceLoadLogParams*)params;
4375 : return dlt_daemon_log_internal(
4376 : log_params->daemon, log_params->daemon_local, (char *)text, loglevel,
4377 : log_params->app_id, DLT_TRACE_LOAD_CONTEXT_ID, log_params->verbose);
4378 : }
4379 : #endif
4380 :
4381 :
4382 : /**
4383 : \}
4384 : */
|