Line data Source code
1 : /*
2 : * SPDX license identifier: MPL-2.0
3 : *
4 : * Copyright (C) 2015 Advanced Driver Information Technology.
5 : * This code is developed by Advanced Driver Information Technology.
6 : * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
7 : *
8 : * This file is part of COVESA Project DLT - Diagnostic Log and Trace.
9 : *
10 : * This Source Code Form is subject to the terms of the
11 : * Mozilla Public License (MPL), v. 2.0.
12 : * If a copy of the MPL was not distributed with this file,
13 : * You can obtain one at http://mozilla.org/MPL/2.0/.
14 : *
15 : * For further information see http://www.covesa.org/.
16 : */
17 :
18 : /*!
19 : * \author
20 : * Christoph Lipka <clipka@jp.adit-jv.com>
21 : * Saya Sugiura <ssugiura@jp.adit-jv.com>
22 : *
23 : * \copyright Copyright © 2015-2018 Advanced Driver Information Technology. \n
24 : * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
25 : *
26 : * \file dlt_gateway.c
27 : */
28 :
29 : #include <stdlib.h>
30 : #include <stdio.h>
31 : #include <string.h>
32 : #include <syslog.h>
33 : #include <arpa/inet.h>
34 : #include <sys/socket.h>
35 : #include <netinet/in.h>
36 : #include <netdb.h>
37 : #include <limits.h>
38 : #include <errno.h>
39 : #include "dlt_gateway.h"
40 : #include "dlt_gateway_internal.h"
41 : #include "dlt_config_file_parser.h"
42 : #include "dlt_common.h"
43 : #include "dlt_log.h"
44 : #include "dlt-daemon_cfg.h"
45 : #include "dlt_daemon_common_cfg.h"
46 : #include "dlt_daemon_event_handler.h"
47 : #include "dlt_daemon_connection.h"
48 : #include "dlt_daemon_client.h"
49 : #include "dlt_daemon_offline_logstorage.h"
50 :
51 : /**
52 : * Check if given string is a valid IP address
53 : *
54 : * @param con DltGatewayConnection to be updated
55 : * @param value string to be tested
56 : * @return Value from DltReturnValue enum
57 : */
58 7 : DLT_STATIC DltReturnValue dlt_gateway_check_ip(DltGatewayConnection *con, char *value)
59 : {
60 7 : if ((con == NULL) || (value == NULL)) {
61 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
62 1 : return DLT_RETURN_WRONG_PARAMETER;
63 : }
64 :
65 : int ret = DLT_RETURN_ERROR;
66 : #ifdef DLT_USE_IPv6
67 : struct sockaddr_in6 sa6;
68 6 : ret = inet_pton(AF_INET6, value, &(sa6.sin6_addr));
69 : #else
70 : struct sockaddr_in sa;
71 : ret = inet_pton(AF_INET, value, &(sa.sin_addr));
72 : #endif
73 :
74 : /* valid IP address */
75 6 : if (ret != 0) {
76 6 : con->ip_address = strdup(value);
77 :
78 6 : if (con->ip_address == NULL) {
79 0 : dlt_log(LOG_ERR, "Cannot copy passive node IP address string\n");
80 0 : return DLT_RETURN_ERROR;
81 : }
82 :
83 : return DLT_RETURN_OK;
84 : }
85 : else {
86 0 : dlt_log(LOG_ERR, "IP address is not valid\n");
87 : }
88 :
89 0 : return DLT_RETURN_ERROR;
90 : }
91 :
92 : /**
93 : * Check port number
94 : *
95 : * @param con DltGatewayConnection to be updated
96 : * @param value string to be tested
97 : * @return Value from DltReturnValue enum
98 : */
99 9 : DLT_STATIC DltReturnValue dlt_gateway_check_port(DltGatewayConnection *con,
100 : char *value)
101 : {
102 : long int tmp = -1;
103 :
104 9 : if ((con == NULL) || (value == NULL)) {
105 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
106 1 : return DLT_RETURN_WRONG_PARAMETER;
107 : }
108 :
109 8 : errno = 0;
110 8 : tmp = strtol(value, NULL, 10);
111 8 : if ((errno == ERANGE && (tmp == LONG_MAX || tmp == LONG_MIN))
112 8 : || (errno != 0 && tmp == 0)) {
113 0 : dlt_vlog(LOG_ERR, "%s: cannot convert port number\n", __func__);
114 0 : return DLT_RETURN_ERROR;
115 : }
116 :
117 : /* port ranges for unprivileged applications */
118 8 : if ((tmp > IPPORT_RESERVED) && ((unsigned)tmp <= USHRT_MAX))
119 : {
120 6 : con->port = (int)tmp;
121 6 : return DLT_RETURN_OK;
122 : }
123 : else {
124 2 : dlt_log(LOG_ERR, "Port number is invalid\n");
125 : }
126 :
127 2 : return DLT_RETURN_ERROR;
128 : }
129 :
130 : /**
131 : * Check ECU name
132 : *
133 : * @param con DltGatewayConnection to be updated
134 : * @param value string to be used as ECU identifier
135 : * @return Value from DltReturnValue enum
136 : */
137 6 : DLT_STATIC DltReturnValue dlt_gateway_check_ecu(DltGatewayConnection *con,
138 : char *value)
139 : {
140 6 : if ((con == NULL) || (value == NULL)) {
141 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
142 1 : return DLT_RETURN_WRONG_PARAMETER;
143 : }
144 :
145 5 : con->ecuid = strdup(value);
146 :
147 5 : if (con->ecuid == NULL)
148 0 : return DLT_RETURN_ERROR;
149 :
150 : return DLT_RETURN_OK;
151 : }
152 :
153 : /**
154 : * Check connection trigger
155 : *
156 : * @param con DltGatewayConnection to be updated
157 : * @param value string to be tested
158 : * @return Value from DltReturnValue enum
159 : */
160 7 : DLT_STATIC DltReturnValue dlt_gateway_check_connect_trigger(DltGatewayConnection *con,
161 : char *value)
162 : {
163 7 : if ((con == NULL) || (value == NULL)) {
164 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
165 1 : return DLT_RETURN_WRONG_PARAMETER;
166 : }
167 :
168 6 : if (strncasecmp(value, "OnStartup", strlen("OnStartup")) == 0) {
169 5 : con->trigger = DLT_GATEWAY_ON_STARTUP;
170 : }
171 1 : else if (strncasecmp(value, "OnDemand", strlen("OnDemand")) == 0)
172 : {
173 0 : con->trigger = DLT_GATEWAY_ON_DEMAND;
174 : }
175 : else {
176 1 : dlt_log(LOG_ERR, "Wrong connection trigger state given.\n");
177 1 : con->trigger = DLT_GATEWAY_UNDEFINED;
178 1 : return DLT_RETURN_ERROR;
179 : }
180 :
181 : return DLT_RETURN_OK;
182 : }
183 :
184 : /**
185 : * Check connection timeout value
186 : *
187 : * @param con DltGatewayConnection to be updated
188 : * @param value string to be tested
189 : * @return Value from DltReturnValue enum
190 : */
191 7 : DLT_STATIC DltReturnValue dlt_gateway_check_timeout(DltGatewayConnection *con,
192 : char *value)
193 : {
194 7 : if ((con == NULL) || (value == NULL)) {
195 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
196 1 : return DLT_RETURN_WRONG_PARAMETER;
197 : }
198 :
199 6 : con->timeout = (int)strtol(value, NULL, 10);
200 :
201 :
202 6 : if (con->timeout >= 0)
203 5 : return DLT_RETURN_OK;
204 :
205 : return DLT_RETURN_ERROR;
206 : }
207 :
208 : /**
209 : * Check connection interval value in General section
210 : *
211 : * @param con DltGateway to be updated
212 : * @param value string to be tested
213 : * @return Value from DltReturnValue enum
214 : */
215 0 : DLT_STATIC DltReturnValue dlt_gateway_check_interval(DltGateway *gateway,
216 : char *value)
217 : {
218 0 : if ((gateway == NULL) || (value == NULL)) {
219 0 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
220 0 : return DLT_RETURN_WRONG_PARAMETER;
221 : }
222 :
223 0 : gateway->interval = (int)strtol(value, NULL, 10);
224 :
225 0 : if (gateway->interval > 0)
226 0 : return DLT_RETURN_OK;
227 :
228 : return DLT_RETURN_ERROR;
229 : }
230 :
231 : /**
232 : * Check the value for SendSerialHeader
233 : *
234 : * @param con DltGatewayConnection to be updated
235 : * @param value string to be tested
236 : * @return Value from DltReturnValue enum
237 : */
238 6 : DLT_STATIC DltReturnValue dlt_gateway_check_send_serial(DltGatewayConnection *con,
239 : char *value)
240 : {
241 6 : if ((con == NULL) || (value == NULL)) {
242 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
243 1 : return DLT_RETURN_WRONG_PARAMETER;
244 : }
245 :
246 5 : con->send_serial = !!((int)strtol(value, NULL, 10));
247 :
248 5 : return DLT_RETURN_OK;
249 : }
250 :
251 : /**
252 : * Allocate passive control messages
253 : *
254 : * @param con DltGatewayConnection to be updated
255 : * @return Value from DltReturnValue enum
256 : */
257 17 : DLT_STATIC DltReturnValue dlt_gateway_allocate_control_messages(DltGatewayConnection *con)
258 : {
259 17 : if (con == NULL) {
260 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
261 1 : return DLT_RETURN_WRONG_PARAMETER;
262 : }
263 :
264 16 : if (con->p_control_msgs == NULL) {
265 7 : con->p_control_msgs = calloc(1, sizeof(DltPassiveControlMessage));
266 :
267 7 : if (!con->p_control_msgs) {
268 0 : dlt_log(LOG_ERR,
269 : "Passive Control Message could not be allocated\n");
270 0 : return DLT_RETURN_ERROR;
271 : }
272 : }
273 : else {
274 9 : con->p_control_msgs->next = calloc(1, sizeof(DltPassiveControlMessage));
275 :
276 9 : if (!con->p_control_msgs->next) {
277 0 : dlt_log(LOG_ERR,
278 : "Passive Control Message could not be allocated\n");
279 0 : return DLT_RETURN_ERROR;
280 : }
281 :
282 9 : con->p_control_msgs = con->p_control_msgs->next;
283 : }
284 :
285 : return DLT_RETURN_OK;
286 : }
287 :
288 : /**
289 : * Check the specified control messages identifier
290 : *
291 : * @param con DltGatewayConnection to be updated
292 : * @param value string to be tested
293 : * @return Value from DltReturnValue enum
294 : */
295 6 : DLT_STATIC DltReturnValue dlt_gateway_check_control_messages(DltGatewayConnection *con,
296 : char *value)
297 : {
298 : /* list of allowed clients given */
299 : char *token = NULL;
300 6 : char *rest = NULL;
301 : DltPassiveControlMessage *head = NULL;
302 :
303 6 : if ((con == NULL) || (value == NULL)) {
304 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
305 1 : return DLT_RETURN_WRONG_PARAMETER;
306 : }
307 :
308 5 : if (strlen(value) == 0)
309 : return DLT_RETURN_OK;
310 :
311 : /* set on startup control msg id and interval*/
312 5 : token = strtok_r(value, ",", &rest);
313 :
314 18 : while (token != NULL) {
315 13 : if (dlt_gateway_allocate_control_messages(con) != DLT_RETURN_OK) {
316 0 : dlt_log(LOG_ERR,
317 : "Passive Control Message could not be allocated\n");
318 0 : return DLT_RETURN_ERROR;
319 : }
320 :
321 13 : con->p_control_msgs->id = strtol(token, NULL, 16);
322 13 : con->p_control_msgs->user_id = DLT_SERVICE_ID_PASSIVE_NODE_CONNECT;
323 13 : con->p_control_msgs->type = CONTROL_MESSAGE_ON_STARTUP;
324 13 : con->p_control_msgs->req = CONTROL_MESSAGE_NOT_REQUESTED;
325 13 : con->p_control_msgs->interval = -1;
326 :
327 13 : if (head == NULL)
328 : head = con->p_control_msgs;
329 :
330 13 : if ((errno == EINVAL) || (errno == ERANGE)) {
331 0 : dlt_vlog(LOG_ERR,
332 : "Control message ID is not an integer: %s\n",
333 : token);
334 0 : return DLT_RETURN_ERROR;
335 : }
336 13 : else if ((con->p_control_msgs->id < DLT_SERVICE_ID_SET_LOG_LEVEL) ||
337 : (con->p_control_msgs->id >= DLT_SERVICE_ID_LAST_ENTRY))
338 : {
339 0 : dlt_vlog(LOG_ERR,
340 : "Control message ID is not valid: %s\n",
341 : token);
342 0 : return DLT_RETURN_ERROR;
343 : }
344 :
345 13 : token = strtok_r(NULL, ",", &rest);
346 : }
347 :
348 : /* get back to head */
349 5 : con->p_control_msgs = head;
350 5 : con->head = head;
351 :
352 5 : return DLT_RETURN_OK;
353 : }
354 :
355 : /**
356 : * Check the specified periodic control messages identifier
357 : *
358 : * @param con DltGatewayConnection to be updated
359 : * @param value string to be tested
360 : * @return Value from DltReturnValue enum
361 : */
362 2 : DLT_STATIC DltReturnValue dlt_gateway_check_periodic_control_messages(
363 : DltGatewayConnection *con,
364 : char *value)
365 : {
366 : char *token = NULL;
367 2 : char *rest = NULL;
368 : DltPassiveControlMessage *head = NULL;
369 :
370 2 : if ((con == NULL) || (value == NULL)) {
371 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
372 1 : return DLT_RETURN_WRONG_PARAMETER;
373 : }
374 :
375 1 : if (strlen(value) == 0)
376 : return DLT_RETURN_OK;
377 :
378 : /* store head address */
379 1 : head = con->p_control_msgs;
380 :
381 : /* set periodic control msg id and interval*/
382 1 : token = strtok_r(value, ",", &rest);
383 :
384 3 : while (token != NULL) {
385 : char *p_token = NULL;
386 2 : char *p_rest = NULL;
387 : uint32_t id = 0;
388 :
389 2 : p_token = strtok_r(token, ":", &p_rest);
390 :
391 2 : if ((p_token != NULL) && (strlen(p_token) != 0)) {
392 2 : id = strtol(p_token, NULL, 16);
393 :
394 : /* get back to head */
395 2 : con->p_control_msgs = head;
396 :
397 : /* check if there is already id set in p_control_msgs */
398 3 : while (con->p_control_msgs != NULL) {
399 1 : if (con->p_control_msgs->id == id) {
400 0 : con->p_control_msgs->type = CONTROL_MESSAGE_BOTH;
401 0 : con->p_control_msgs->interval = strtol(p_rest, NULL, 10);
402 :
403 0 : if (con->p_control_msgs->interval <= 0)
404 0 : dlt_vlog(LOG_WARNING,
405 : "%s interval is %d. It won't be send periodically.\n",
406 : dlt_get_service_name(con->p_control_msgs->id),
407 : con->p_control_msgs->interval);
408 :
409 : break;
410 : }
411 :
412 1 : con->p_control_msgs = con->p_control_msgs->next;
413 : }
414 :
415 : /* if the id is not added yet, p_control_msgs supposed to be NULL */
416 2 : if (con->p_control_msgs == NULL) {
417 : /* get back to head */
418 2 : con->p_control_msgs = head;
419 :
420 : /* go to last pointer */
421 2 : while (con->p_control_msgs != NULL) {
422 1 : if (con->p_control_msgs->next == NULL)
423 : break;
424 :
425 0 : con->p_control_msgs = con->p_control_msgs->next;
426 : }
427 :
428 2 : if (dlt_gateway_allocate_control_messages(con) != DLT_RETURN_OK) {
429 0 : dlt_log(LOG_ERR,
430 : "Passive Control Message could not be allocated\n");
431 0 : return DLT_RETURN_ERROR;
432 : }
433 :
434 2 : con->p_control_msgs->id = id;
435 2 : con->p_control_msgs->user_id = DLT_SERVICE_ID_PASSIVE_NODE_CONNECT;
436 2 : con->p_control_msgs->type = CONTROL_MESSAGE_PERIODIC;
437 2 : con->p_control_msgs->req = CONTROL_MESSAGE_NOT_REQUESTED;
438 2 : con->p_control_msgs->interval = strtol(p_rest, NULL, 10);
439 :
440 2 : if (con->p_control_msgs->interval <= 0)
441 0 : dlt_vlog(LOG_WARNING,
442 : "%s interval is %d. It won't be send periodically.\n",
443 : dlt_get_service_name(con->p_control_msgs->id),
444 : con->p_control_msgs->interval);
445 :
446 2 : if (head == NULL)
447 1 : head = con->p_control_msgs;
448 : }
449 : }
450 :
451 2 : if ((errno == EINVAL) || (errno == ERANGE)) {
452 0 : dlt_vlog(LOG_ERR,
453 : "Control message ID is not an integer: %s\n",
454 : p_token);
455 0 : return DLT_RETURN_ERROR;
456 : }
457 2 : else if ((con->p_control_msgs->id < DLT_SERVICE_ID_SET_LOG_LEVEL) ||
458 : (con->p_control_msgs->id >= DLT_SERVICE_ID_LAST_ENTRY))
459 : {
460 0 : dlt_vlog(LOG_ERR,
461 : "Control message ID is not valid: %s\n",
462 : p_token);
463 0 : return DLT_RETURN_ERROR;
464 : }
465 :
466 2 : token = strtok_r(NULL, ",", &rest);
467 : }
468 :
469 : /* get back to head */
470 1 : con->p_control_msgs = head;
471 1 : con->head = head;
472 :
473 1 : return DLT_RETURN_OK;
474 : }
475 :
476 : /**
477 : * Expected entries for a passive node configuration
478 : * Caution: after changing entries here,
479 : * dlt_gateway_check_param needs to be updated as well
480 : * */
481 : DLT_STATIC DltGatewayConf configuration_entries[GW_CONF_COUNT] = {
482 : [GW_CONF_IP_ADDRESS] = {
483 : .key = "IPaddress",
484 : .func = dlt_gateway_check_ip,
485 : .is_opt = 0
486 : },
487 : [GW_CONF_PORT] = {
488 : .key = "Port",
489 : .func = dlt_gateway_check_port,
490 : .is_opt = 1
491 : },
492 : [GW_CONF_ECUID] = {
493 : .key = "EcuID",
494 : .func = dlt_gateway_check_ecu,
495 : .is_opt = 0
496 : },
497 : [GW_CONF_CONNECT] = {
498 : .key = "Connect",
499 : .func = dlt_gateway_check_connect_trigger,
500 : .is_opt = 1
501 : },
502 : [GW_CONF_TIMEOUT] = {
503 : .key = "Timeout",
504 : .func = dlt_gateway_check_timeout,
505 : .is_opt = 0
506 : },
507 : [GW_CONF_SEND_CONTROL] = {
508 : .key = "SendControl",
509 : .func = dlt_gateway_check_control_messages,
510 : .is_opt = 1
511 : },
512 : [GW_CONF_SEND_PERIODIC_CONTROL] = {
513 : .key = "SendPeriodicControl",
514 : .func = dlt_gateway_check_periodic_control_messages,
515 : .is_opt = 1
516 : },
517 : [GW_CONF_SEND_SERIAL_HEADER] = {
518 : .key = "SendSerialHeader",
519 : .func = dlt_gateway_check_send_serial,
520 : .is_opt = 1
521 : }
522 : };
523 :
524 : DLT_STATIC DltGatewayGeneralConf general_entries[GW_CONF_COUNT] = {
525 : [GW_CONF_GENERAL_INTERVAL] = {
526 : .key = "Interval",
527 : .func = dlt_gateway_check_interval,
528 : .is_opt = 1
529 : }
530 : };
531 :
532 : #define DLT_GATEWAY_NUM_PROPERTIES_MAX GW_CONF_COUNT
533 :
534 : /**
535 : * Check if gateway connection general configuration parameter is valid.
536 : *
537 : * @param gateway DltGateway
538 : * @param ctype DltGatwayGeneralConnection property
539 : * @param value specified property value from configuration file
540 : * @return Value from DltReturnValue enum
541 : */
542 0 : DLT_STATIC DltReturnValue dlt_gateway_check_general_param(DltGateway *gateway,
543 : DltGatewayGeneralConfType ctype,
544 : char *value)
545 : {
546 0 : if ((gateway == NULL) || (value == NULL)) {
547 0 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
548 0 : return DLT_RETURN_WRONG_PARAMETER;
549 : }
550 :
551 0 : if (ctype < GW_CONF_GENEREL_COUNT)
552 0 : return general_entries[ctype].func(gateway, value);
553 :
554 : return DLT_RETURN_ERROR;
555 : }
556 :
557 : /**
558 : * Check if gateway connection configuration parameter is valid.
559 : *
560 : * @param gateway DltGateway
561 : * @param con DltGatewayConnection
562 : * @param ctype DltGatwayConnection property
563 : * @param value specified property value from configuration file
564 : * @return Value from DltReturnValue enum
565 : */
566 32 : DLT_STATIC DltReturnValue dlt_gateway_check_param(DltGateway *gateway,
567 : DltGatewayConnection *con,
568 : DltGatewayConfType ctype,
569 : char *value)
570 : {
571 32 : if ((gateway == NULL) || (con == NULL) || (value == NULL)) {
572 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
573 1 : return DLT_RETURN_WRONG_PARAMETER;
574 : }
575 :
576 31 : if (ctype < GW_CONF_COUNT)
577 31 : return configuration_entries[ctype].func(con, value);
578 :
579 : return DLT_RETURN_ERROR;
580 : }
581 :
582 : /**
583 : * Store gateway connection in internal data structure
584 : *
585 : * @param gateway DltGatway
586 : * @param tmp DltGatewayConnection
587 : * @param verbose verbose flag
588 : * @return 0 on success, -1 otherwise
589 : */
590 7 : int dlt_gateway_store_connection(DltGateway *gateway,
591 : DltGatewayConnection *tmp,
592 : int verbose)
593 : {
594 : int i = 0;
595 :
596 7 : PRINT_FUNCTION_VERBOSE(verbose);
597 :
598 7 : if ((gateway == NULL) || (tmp == NULL)) {
599 2 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
600 2 : return DLT_RETURN_WRONG_PARAMETER;
601 : }
602 :
603 : /* find next free entry in connection array */
604 5 : while (i < gateway->num_connections) {
605 5 : if (gateway->connections[i].status == DLT_GATEWAY_UNINITIALIZED)
606 : break;
607 :
608 0 : i++;
609 : }
610 :
611 : /* store values */
612 5 : gateway->connections[i].ip_address = strdup(tmp->ip_address);
613 5 : gateway->connections[i].ecuid = strdup(tmp->ecuid);
614 5 : gateway->connections[i].sock_domain = tmp->sock_domain;
615 5 : gateway->connections[i].sock_type = tmp->sock_type;
616 5 : gateway->connections[i].sock_protocol = tmp->sock_protocol;
617 5 : gateway->connections[i].port = tmp->port;
618 5 : gateway->connections[i].trigger = tmp->trigger;
619 5 : gateway->connections[i].timeout = tmp->timeout;
620 5 : gateway->connections[i].handle = 0;
621 5 : gateway->connections[i].status = DLT_GATEWAY_INITIALIZED;
622 5 : gateway->connections[i].p_control_msgs = tmp->p_control_msgs;
623 5 : gateway->connections[i].head = tmp->head;
624 5 : gateway->connections[i].send_serial = tmp->send_serial;
625 :
626 5 : if (dlt_client_init_port(&gateway->connections[i].client,
627 : gateway->connections[i].port,
628 : verbose) != 0) {
629 0 : free(gateway->connections[i].ip_address);
630 0 : gateway->connections[i].ip_address = NULL;
631 0 : free(gateway->connections[i].ecuid);
632 0 : gateway->connections[i].ecuid = NULL;
633 0 : free(gateway->connections[i].p_control_msgs);
634 0 : gateway->connections[i].p_control_msgs = NULL;
635 0 : dlt_log(LOG_CRIT, "dlt_client_init_port() failed for gateway connection\n");
636 0 : return DLT_RETURN_ERROR;
637 : }
638 :
639 : /* setup DltClient Structure */
640 5 : if (dlt_client_set_server_ip(&gateway->connections[i].client,
641 5 : gateway->connections[i].ip_address) == -1) {
642 0 : dlt_log(LOG_ERR,
643 : "dlt_client_set_server_ip() failed for gateway connection \n");
644 0 : return DLT_RETURN_ERROR;
645 : }
646 :
647 : return DLT_RETURN_OK;
648 : }
649 :
650 : /**
651 : * Read configuration file and initialize connection data structures
652 : *
653 : * @param gateway DltGateway
654 : * @param config_file Gateway configuration
655 : * @param verbose verbose flag
656 : * @return 0 on success, -1 otherwise
657 : */
658 5 : int dlt_gateway_configure(DltGateway *gateway, char *config_file, int verbose)
659 : {
660 : int ret = 0;
661 : int i = 0;
662 : DltConfigFile *file = NULL;
663 5 : int num_sections = 0;
664 :
665 5 : PRINT_FUNCTION_VERBOSE(verbose);
666 :
667 5 : if ((gateway == NULL) || (config_file == 0) || (config_file[0] == '\0')) {
668 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
669 1 : return DLT_RETURN_WRONG_PARAMETER;
670 : }
671 :
672 : /* read configuration file */
673 4 : file = dlt_config_file_init(config_file);
674 4 : if(file == NULL) {
675 : return DLT_RETURN_ERROR;
676 : }
677 :
678 : /* get number of entries and allocate memory to store information */
679 4 : ret = dlt_config_file_get_num_sections(file, &num_sections);
680 4 : if (ret != 0) {
681 0 : dlt_config_file_release(file);
682 0 : dlt_log(LOG_ERR, "Invalid number of sections in configuration file\n");
683 0 : return DLT_RETURN_ERROR;
684 : }
685 :
686 4 : ret = dlt_config_file_check_section_name_exists(file, DLT_GATEWAY_GENERAL_SECTION_NAME);
687 4 : if (ret == -1) {
688 : /*
689 : * No General section in configuration file.
690 : * Try to use default for interval.
691 : */
692 4 : gateway->num_connections = num_sections;
693 4 : dlt_vlog(LOG_WARNING,
694 : "Missing General section in gateway. Using default interval %d (secs)\n",
695 : gateway->interval);
696 : }
697 : else {
698 : /*
699 : * Since the General section is also counted in num_sections,
700 : * so number of connections must be number of sections - 1.
701 : */
702 0 : gateway->num_connections = num_sections - 1;
703 : }
704 :
705 4 : gateway->connections = calloc(gateway->num_connections,
706 : sizeof(DltGatewayConnection));
707 :
708 4 : if (gateway->connections == NULL) {
709 0 : dlt_config_file_release(file);
710 0 : dlt_log(LOG_CRIT, "Memory allocation for gateway connections failed\n");
711 0 : return DLT_RETURN_ERROR;
712 : }
713 :
714 8 : for (i = 0; i < num_sections; i++) {
715 : DltGatewayConnection tmp;
716 : int invalid = 0;
717 : DltGatewayConfType j = 0;
718 : DltGatewayGeneralConfType g = 0;
719 4 : char section[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = { '\0' };
720 4 : char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = { '\0' };
721 :
722 : memset(&tmp, 0, sizeof(tmp));
723 :
724 : /* Set default */
725 4 : tmp.send_serial = gateway->send_serial;
726 4 : tmp.port = DLT_DAEMON_TCP_PORT;
727 :
728 4 : ret = dlt_config_file_get_section_name(file, i, section);
729 4 : if (ret != 0) {
730 0 : dlt_log(LOG_WARNING, "Get section name failed\n");
731 0 : continue;
732 : }
733 :
734 4 : if (strncmp(section, DLT_GATEWAY_GENERAL_SECTION_NAME,
735 : sizeof(DLT_GATEWAY_GENERAL_SECTION_NAME)) == 0) {
736 0 : for (g = 0; g < GW_CONF_GENEREL_COUNT; g++) {
737 0 : ret = dlt_config_file_get_value(file,
738 : section,
739 0 : general_entries[g].key,
740 : value);
741 :
742 0 : if ((ret != 0) && general_entries[g].is_opt) {
743 : /* Use default values for this key */
744 0 : dlt_vlog(LOG_WARNING,
745 : "Using default for %s.\n",
746 : general_entries[g].key);
747 0 : continue;
748 : }
749 0 : else if (ret != 0)
750 : {
751 0 : dlt_vlog(LOG_WARNING,
752 : "Missing configuration for %s.\n",
753 : general_entries[g].key);
754 0 : break;
755 : }
756 :
757 : /* check value and store general configuration */
758 0 : ret = dlt_gateway_check_general_param(gateway, g, value);
759 :
760 0 : if (ret != 0)
761 0 : dlt_vlog(LOG_ERR,
762 : "Configuration %s = %s is invalid. Using default.\n",
763 : general_entries[g].key, value);
764 : }
765 : }
766 : else {
767 36 : for (j = 0; j < GW_CONF_COUNT; j++) {
768 32 : ret = dlt_config_file_get_value(file,
769 : section,
770 32 : configuration_entries[j].key,
771 : value);
772 :
773 32 : if ((ret != 0) && configuration_entries[j].is_opt) {
774 : /* Use default values for this key */
775 4 : dlt_vlog(LOG_WARNING,
776 : "Using default for %s.\n",
777 : configuration_entries[j].key);
778 4 : continue;
779 : }
780 28 : else if (ret != 0)
781 : {
782 0 : dlt_vlog(LOG_WARNING,
783 : "Missing configuration for %s.\n",
784 : configuration_entries[j].key);
785 : invalid = 1;
786 0 : break;
787 : }
788 :
789 : /* check value and store temporary */
790 28 : ret = dlt_gateway_check_param(gateway, &tmp, j, value);
791 :
792 28 : if (ret != 0)
793 0 : dlt_vlog(LOG_ERR,
794 : "Configuration %s = %s is invalid.\n"
795 : "Using default.\n",
796 : configuration_entries[j].key, value);
797 : }
798 :
799 4 : if (!tmp.ip_address) {
800 : invalid = 1;
801 : }
802 :
803 4 : if (invalid) {
804 0 : dlt_vlog(LOG_ERR,
805 : "%s configuration is invalid.\n"
806 : "Ignoring.\n",
807 : section);
808 : }
809 : else {
810 4 : ret = dlt_gateway_store_connection(gateway, &tmp, verbose);
811 :
812 4 : if (ret != 0)
813 0 : dlt_log(LOG_ERR, "Storing gateway connection data failed\n");
814 : }
815 : }
816 :
817 : /* strdup used inside some get_value function */
818 4 : if (tmp.ecuid != NULL) {
819 4 : free(tmp.ecuid);
820 4 : tmp.ecuid = NULL;
821 : }
822 4 : if (tmp.ip_address != NULL) {
823 4 : free(tmp.ip_address);
824 : tmp.ip_address = NULL;
825 : }
826 : }
827 :
828 4 : dlt_config_file_release(file);
829 4 : return ret;
830 : }
831 :
832 4 : int dlt_gateway_init(DltDaemonLocal *daemon_local, int verbose)
833 : {
834 4 : PRINT_FUNCTION_VERBOSE(verbose);
835 :
836 4 : if (daemon_local == NULL) {
837 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
838 1 : return DLT_RETURN_WRONG_PARAMETER;
839 : }
840 :
841 3 : DltGateway *gateway = &daemon_local->pGateway;
842 :
843 : if (gateway != NULL) {
844 : /* Get default value from daemon_local */
845 3 : gateway->send_serial = daemon_local->flags.lflag;
846 3 : gateway->interval = DLT_GATEWAY_TIMER_DEFAULT_INTERVAL;
847 :
848 3 : if (dlt_gateway_configure(gateway,
849 3 : daemon_local->flags.gatewayConfigFile,
850 : verbose) != 0) {
851 0 : dlt_log(LOG_ERR, "Gateway initialization failed\n");
852 0 : return DLT_RETURN_ERROR;
853 : }
854 : }
855 : else {
856 : dlt_log(LOG_CRIT, "Pointer to Gateway structure is NULL\n");
857 : return DLT_RETURN_ERROR;
858 : }
859 :
860 : /* ignore return value */
861 3 : dlt_gateway_establish_connections(gateway, daemon_local, verbose);
862 :
863 3 : return DLT_RETURN_OK;
864 : }
865 :
866 10 : void dlt_gateway_deinit(DltGateway *gateway, int verbose)
867 : {
868 : DltPassiveControlMessage *msg;
869 : int i = 0;
870 :
871 10 : if (gateway == NULL) {
872 0 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
873 0 : return;
874 : }
875 :
876 10 : PRINT_FUNCTION_VERBOSE(verbose);
877 :
878 12 : for (i = 0; i < gateway->num_connections; i++) {
879 2 : DltGatewayConnection *c = &gateway->connections[i];
880 2 : dlt_client_cleanup(&c->client, verbose);
881 2 : free(c->ip_address);
882 2 : c->ip_address = NULL;
883 2 : free(c->ecuid);
884 2 : c->ecuid = NULL;
885 :
886 6 : while (c->p_control_msgs != NULL) {
887 4 : msg = c->p_control_msgs->next;
888 4 : free(c->p_control_msgs);
889 4 : c->p_control_msgs = msg;
890 : }
891 : }
892 :
893 10 : free(gateway->connections);
894 10 : gateway->connections = NULL;
895 : }
896 :
897 : /**
898 : * If connection to passive node established, add to event loop
899 : *
900 : * @param daemon_local DltDaemonLocal
901 : * @param con DltGatewayConnection
902 : * @param verbose verbose flag
903 : * @return 0 on success, -1 otherwise
904 : */
905 3 : DLT_STATIC int dlt_gateway_add_to_event_loop(DltDaemonLocal *daemon_local,
906 : DltGatewayConnection *con,
907 : int verbose)
908 : {
909 : DltPassiveControlMessage *control_msg = NULL;
910 : int sendtime = 1;
911 :
912 3 : if ((daemon_local == NULL) || (con == NULL)) {
913 0 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
914 0 : return DLT_RETURN_WRONG_PARAMETER;
915 : }
916 :
917 : /* connection to passive node established, add to event loop */
918 3 : con->status = DLT_GATEWAY_CONNECTED;
919 3 : con->reconnect_cnt = 0;
920 3 : con->timeout_cnt = 0;
921 3 : con->sendtime_cnt = 0;
922 :
923 : /* setup dlt connection and add to poll event loop here */
924 3 : if (dlt_connection_create(daemon_local,
925 : &daemon_local->pEvent,
926 : con->client.sock,
927 : POLLIN,
928 : DLT_CONNECTION_GATEWAY) != 0) {
929 0 : dlt_log(LOG_ERR, "Gateway connection creation failed\n");
930 0 : return DLT_RETURN_ERROR;
931 : }
932 :
933 : /* immediately send configured control messages */
934 3 : control_msg = con->p_control_msgs;
935 :
936 9 : while (control_msg != NULL) {
937 6 : if ((control_msg->type == CONTROL_MESSAGE_ON_STARTUP) ||
938 : (control_msg->type == CONTROL_MESSAGE_BOTH)) {
939 6 : if (dlt_gateway_send_control_message(con,
940 : control_msg,
941 : NULL,
942 : verbose) == DLT_RETURN_OK)
943 6 : control_msg->req = CONTROL_MESSAGE_REQUESTED;
944 : }
945 :
946 : /* multiply periodic sending time */
947 6 : if (((control_msg->type == CONTROL_MESSAGE_PERIODIC) ||
948 0 : (control_msg->type == CONTROL_MESSAGE_BOTH)) &&
949 0 : (control_msg->interval > 0))
950 0 : sendtime *= control_msg->interval;
951 :
952 6 : control_msg = control_msg->next;
953 : }
954 :
955 : /* set periodic sending time */
956 3 : con->sendtime = sendtime;
957 3 : con->sendtime_cnt = con->sendtime;
958 :
959 3 : return DLT_RETURN_OK;
960 : }
961 :
962 6 : int dlt_gateway_establish_connections(DltGateway *gateway,
963 : DltDaemonLocal *daemon_local,
964 : int verbose)
965 : {
966 : int i = 0;
967 : int ret = 0;
968 :
969 6 : PRINT_FUNCTION_VERBOSE(verbose);
970 :
971 6 : if ((gateway == NULL) || (daemon_local == NULL)) {
972 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
973 1 : return DLT_RETURN_WRONG_PARAMETER;
974 : }
975 :
976 10 : for (i = 0; i < gateway->num_connections; i++) {
977 5 : DltGatewayConnection *con = &(gateway->connections[i]);
978 : DltPassiveControlMessage *control_msg = NULL;
979 :
980 5 : if ((con->status != DLT_GATEWAY_CONNECTED) &&
981 5 : (con->trigger != DLT_GATEWAY_ON_DEMAND) &&
982 : (con->trigger != DLT_GATEWAY_DISABLED)) {
983 5 : ret = dlt_client_connect(&con->client, verbose);
984 :
985 5 : if (ret == 0) {
986 : /* setup dlt connection and add to poll event loop here */
987 3 : if (dlt_gateway_add_to_event_loop(daemon_local, con, verbose) != DLT_RETURN_OK) {
988 0 : dlt_log(LOG_ERR, "Gateway connection creation failed\n");
989 0 : return DLT_RETURN_ERROR;
990 : }
991 : }
992 : else {
993 2 : dlt_log(LOG_DEBUG,
994 : "Passive Node is not up. Connection failed.\n");
995 :
996 2 : con->timeout_cnt++;
997 :
998 2 : if (con->timeout > 0) {
999 0 : if (con->timeout_cnt > con->timeout) {
1000 0 : con->trigger = DLT_GATEWAY_DISABLED;
1001 0 : dlt_log(LOG_WARNING,
1002 : "Passive Node connection retry timed out. "
1003 : "Give up.\n");
1004 : }
1005 : }
1006 2 : else if (con->timeout == 0) {
1007 2 : dlt_vlog(LOG_DEBUG, "Retried [%d] times\n", con->timeout_cnt);
1008 : }
1009 : }
1010 : }
1011 0 : else if ((con->status == DLT_GATEWAY_CONNECTED) &&
1012 0 : (con->trigger != DLT_GATEWAY_DISABLED))
1013 : {
1014 : /* setup dlt connection and add to poll event loop here */
1015 0 : if (dlt_connection_create(daemon_local,
1016 : &daemon_local->pEvent,
1017 : con->client.sock,
1018 : POLLIN,
1019 : DLT_CONNECTION_GATEWAY) != 0) {
1020 0 : dlt_log(LOG_ERR, "Gateway connection creation failed\n");
1021 0 : return DLT_RETURN_ERROR;
1022 : }
1023 :
1024 : /* immediately send periodic configured control messages */
1025 0 : control_msg = con->p_control_msgs;
1026 :
1027 0 : while (control_msg != NULL) {
1028 0 : if ((control_msg->type == CONTROL_MESSAGE_PERIODIC) ||
1029 : (control_msg->type == CONTROL_MESSAGE_BOTH)) {
1030 0 : if (dlt_gateway_send_control_message(con,
1031 : control_msg,
1032 : NULL,
1033 : verbose) == DLT_RETURN_OK)
1034 0 : control_msg->req = CONTROL_MESSAGE_REQUESTED;
1035 : }
1036 :
1037 0 : control_msg = control_msg->next;
1038 : }
1039 :
1040 : /* check sendtime counter */
1041 0 : if (con->sendtime_cnt > 0)
1042 0 : con->sendtime_cnt--;
1043 :
1044 0 : if (con->sendtime_cnt == 0)
1045 0 : con->sendtime_cnt = con->sendtime;
1046 : }
1047 : }
1048 :
1049 : return DLT_RETURN_OK;
1050 : }
1051 :
1052 6 : DltReceiver *dlt_gateway_get_connection_receiver(DltGateway *gateway, int fd)
1053 : {
1054 : int i = 0;
1055 :
1056 6 : if (gateway == NULL) {
1057 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
1058 1 : return NULL;
1059 : }
1060 :
1061 6 : for (i = 0; i < gateway->num_connections; i++) {
1062 5 : DltGatewayConnection *c = &gateway->connections[i];
1063 :
1064 5 : if ((c->status == DLT_GATEWAY_CONNECTED) && (c->client.sock == fd))
1065 4 : return &c->client.receiver;
1066 : }
1067 :
1068 : return NULL;
1069 : }
1070 :
1071 : /**
1072 : * Parse GET_LOG_INFO
1073 : *
1074 : * @param daemon DltDaemon
1075 : * @param ecu Ecu ID
1076 : * @param msg DltMessage
1077 : * @param req 1 if requested from gateway, 0 otherwise
1078 : * @param verbose verbose flag
1079 : * @return Value from DltReturnValue enum
1080 : */
1081 3 : DLT_STATIC DltReturnValue dlt_gateway_parse_get_log_info(DltDaemon *daemon,
1082 : char *ecu,
1083 : DltMessage *msg,
1084 : int req,
1085 : int verbose)
1086 : {
1087 3 : char resp_text[DLT_RECEIVE_BUFSIZE] = { '\0' };
1088 : DltServiceGetLogInfoResponse *resp = NULL;
1089 : AppIDsType app;
1090 : ContextIDsInfoType con;
1091 : int i = 0;
1092 : int j = 0;
1093 :
1094 3 : PRINT_FUNCTION_VERBOSE(verbose);
1095 :
1096 3 : if ((msg == NULL) || (msg->databuffer == NULL)) {
1097 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
1098 1 : return DLT_RETURN_WRONG_PARAMETER;
1099 : }
1100 :
1101 2 : if (dlt_check_rcv_data_size(msg->datasize, sizeof(DltServiceGetLogInfoResponse)) < 0)
1102 : return DLT_RETURN_ERROR;
1103 :
1104 : /* if the request was send from gateway, clear all application and context list */
1105 1 : if (req == CONTROL_MESSAGE_REQUESTED) {
1106 : /* clear application list */
1107 0 : if (dlt_daemon_applications_clear(daemon, ecu, verbose) == DLT_RETURN_ERROR) {
1108 0 : dlt_log(LOG_ERR, "Cannot clear applications list\n");
1109 0 : return DLT_RETURN_ERROR;
1110 : }
1111 :
1112 : /* clear context list */
1113 0 : if (dlt_daemon_contexts_clear(daemon, ecu, verbose) == DLT_RETURN_ERROR) {
1114 0 : dlt_log(LOG_ERR, "Cannot clear contexts list\n");
1115 0 : return DLT_RETURN_ERROR;
1116 : }
1117 : }
1118 :
1119 : /* check response */
1120 1 : if (dlt_message_payload(msg,
1121 : resp_text,
1122 : DLT_RECEIVE_BUFSIZE,
1123 : DLT_OUTPUT_ASCII, 0) != DLT_RETURN_OK) {
1124 0 : dlt_log(LOG_ERR, "GET_LOG_INFO payload failed\n");
1125 0 : return DLT_RETURN_ERROR;
1126 : }
1127 :
1128 : /* prepare pointer to message request */
1129 1 : resp = (DltServiceGetLogInfoResponse *)calloc(1, sizeof(DltServiceGetLogInfoResponse));
1130 :
1131 1 : if (resp == NULL) {
1132 0 : dlt_log(LOG_ERR,
1133 : "Get Log Info Response could not be allocated\n");
1134 0 : return DLT_RETURN_ERROR;
1135 : }
1136 :
1137 1 : if (dlt_set_loginfo_parse_service_id(resp_text, &resp->service_id, &resp->status) != DLT_RETURN_OK) {
1138 0 : dlt_log(LOG_ERR, "Parsing GET_LOG_INFO failed\n");
1139 0 : dlt_client_cleanup_get_log_info(resp);
1140 0 : return DLT_RETURN_ERROR;
1141 : }
1142 :
1143 1 : if (dlt_client_parse_get_log_info_resp_text(resp, resp_text) != DLT_RETURN_OK) {
1144 0 : dlt_log(LOG_ERR, "Parsing GET_LOG_INFO failed\n");
1145 0 : dlt_client_cleanup_get_log_info(resp);
1146 0 : return DLT_RETURN_ERROR;
1147 : }
1148 :
1149 2 : for (i = 0; i < resp->log_info_type.count_app_ids; i++) {
1150 1 : app = resp->log_info_type.app_ids[i];
1151 :
1152 : /* add application */
1153 1 : if (dlt_daemon_application_add(daemon,
1154 : app.app_id,
1155 : 0,
1156 : app.app_description,
1157 : -1,
1158 : ecu,
1159 : verbose) == 0) {
1160 0 : dlt_vlog(LOG_WARNING,
1161 : "%s: dlt_daemon_application_add failed\n",
1162 : __func__);
1163 0 : dlt_client_cleanup_get_log_info(resp);
1164 0 : return DLT_RETURN_ERROR;
1165 : }
1166 :
1167 2 : for (j = 0; j < app.count_context_ids; j++) {
1168 1 : con = app.context_id_info[j];
1169 :
1170 : /* add context */
1171 1 : if (dlt_daemon_context_add(daemon,
1172 : app.app_id,
1173 : con.context_id,
1174 1 : con.log_level,
1175 1 : con.trace_status,
1176 : 0,
1177 : -1,
1178 : con.context_description,
1179 : ecu,
1180 : verbose) == 0) {
1181 0 : dlt_vlog(LOG_WARNING,
1182 : "%s: dlt_daemon_context_add failed for %4s\n",
1183 : __func__,
1184 : app.app_id);
1185 0 : dlt_client_cleanup_get_log_info(resp);
1186 0 : return DLT_RETURN_ERROR;
1187 : }
1188 : }
1189 : }
1190 :
1191 : /* free response */
1192 1 : dlt_client_cleanup_get_log_info(resp);
1193 :
1194 1 : return DLT_RETURN_OK;
1195 : }
1196 :
1197 : /**
1198 : * Parse GET_DEFAULT_LOG_LEVEL
1199 : *
1200 : * @param daemon DltDaemon
1201 : * @param daemon_local DltDaemonLocal
1202 : * @param ecu Ecu ID
1203 : * @param msg DltMessage
1204 : * @param verbose verbose flag
1205 : * @return 0 on success, -1 otherwise
1206 : */
1207 0 : DLT_STATIC int dlt_gateway_parse_get_default_log_level(DltDaemon *daemon,
1208 : DltDaemonLocal *daemon_local,
1209 : char *ecu,
1210 : DltMessage *msg,
1211 : int verbose)
1212 : {
1213 : DltServiceGetDefaultLogLevelResponse *resp = NULL;
1214 : DltGatewayConnection *con = NULL;
1215 :
1216 0 : PRINT_FUNCTION_VERBOSE(verbose);
1217 :
1218 0 : if ((daemon == NULL) || (daemon_local == NULL)) {
1219 0 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
1220 0 : return DLT_RETURN_WRONG_PARAMETER;
1221 : }
1222 :
1223 0 : if (dlt_check_rcv_data_size(msg->datasize,
1224 : sizeof(DltServiceGetDefaultLogLevelResponse)) < 0) {
1225 0 : dlt_log(LOG_ERR, "Received data incomplete.\n");
1226 0 : return DLT_RETURN_ERROR;
1227 : }
1228 :
1229 : /* prepare pointer to message request */
1230 0 : resp = (DltServiceGetDefaultLogLevelResponse *)(msg->databuffer);
1231 :
1232 0 : con = dlt_gateway_get_connection(&daemon_local->pGateway,
1233 : ecu,
1234 : verbose);
1235 :
1236 0 : if (con == NULL) {
1237 0 : dlt_vlog(LOG_ERR, "No information about passive ECU: %s\n",
1238 : ecu);
1239 :
1240 0 : return DLT_RETURN_ERROR;
1241 : }
1242 :
1243 0 : con->default_log_level = resp->log_level;
1244 :
1245 0 : return DLT_RETURN_OK;
1246 : }
1247 :
1248 : /**
1249 : * Service offline logstorage
1250 : *
1251 : * @param daemon DltDaemon
1252 : * @param daemon_local DltDaemonLocal
1253 : * @param verbose int
1254 : * @return 0 on success, -1 otherwise
1255 : */
1256 1 : DLT_STATIC int dlt_gateway_control_service_logstorage(DltDaemon *daemon,
1257 : DltDaemonLocal *daemon_local,
1258 : int verbose)
1259 : {
1260 : unsigned int connection_type = 0;
1261 : int i = 0;
1262 :
1263 1 : if (daemon_local->flags.offlineLogstorageMaxDevices <= 0) {
1264 1 : dlt_log(LOG_INFO,
1265 : "Logstorage functionality not enabled or MAX device set is 0\n");
1266 1 : return DLT_RETURN_ERROR;
1267 : }
1268 :
1269 0 : for (i = 0; i < daemon_local->flags.offlineLogstorageMaxDevices; i++) {
1270 0 : connection_type = daemon->storage_handle[i].connection_type;
1271 :
1272 0 : if (connection_type == DLT_OFFLINE_LOGSTORAGE_DEVICE_CONNECTED)
1273 : /* Check if log level of running application needs an update */
1274 0 : dlt_daemon_logstorage_update_application_loglevel(daemon,
1275 : daemon_local,
1276 : i,
1277 : verbose);
1278 : }
1279 :
1280 : return DLT_RETURN_OK;
1281 : }
1282 :
1283 6 : DltReturnValue dlt_gateway_process_passive_node_messages(DltDaemon *daemon,
1284 : DltDaemonLocal *daemon_local,
1285 : DltReceiver *receiver,
1286 : int verbose)
1287 : {
1288 : int i = 0;
1289 : DltGateway *gateway = NULL;
1290 : DltGatewayConnection *con = NULL;
1291 6 : DltMessage msg = { 0 };
1292 : bool b_reset_receiver = false;
1293 :
1294 6 : if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
1295 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
1296 1 : return DLT_RETURN_WRONG_PARAMETER;
1297 : }
1298 :
1299 5 : PRINT_FUNCTION_VERBOSE(verbose);
1300 :
1301 : gateway = &daemon_local->pGateway;
1302 :
1303 : if (gateway == NULL) {
1304 : dlt_log(LOG_ERR, "Gateway structure is NULL\n");
1305 : return DLT_RETURN_ERROR;
1306 : }
1307 :
1308 5 : for (i = 0; i < gateway->num_connections; i++)
1309 5 : if ((gateway->connections[i].status == DLT_GATEWAY_CONNECTED) && (gateway->connections[i].client.sock == receiver->fd)) {
1310 : con = &gateway->connections[i];
1311 : break;
1312 : }
1313 :
1314 5 : if (con == NULL) {
1315 0 : dlt_log(LOG_ERR, "Cannot associate fd to passive Node connection\n");
1316 0 : return DLT_RETURN_ERROR;
1317 : }
1318 :
1319 : /* now the corresponding passive node connection is available */
1320 5 : if (dlt_message_init(&msg, verbose) == -1) {
1321 0 : dlt_log(LOG_ERR,
1322 : "Cannot initialize DLT message for passive node forwarding\n");
1323 0 : return DLT_RETURN_ERROR;
1324 : }
1325 :
1326 : /* nearly copy and paste of dlt_client_main_loop function */
1327 5 : if (dlt_receiver_receive(receiver) <= 0) {
1328 : /* No more data to be received */
1329 1 : if (dlt_message_free(&msg, verbose) < 0) {
1330 0 : dlt_log(LOG_ERR, "Cannot free DLT message\n");
1331 0 : return DLT_RETURN_ERROR;
1332 : }
1333 :
1334 1 : dlt_log(LOG_WARNING, "Connection to passive node lost\n");
1335 :
1336 1 : if (con->reconnect_cnt < DLT_GATEWAY_RECONNECT_MAX) {
1337 1 : dlt_log(LOG_WARNING, "Try to reconnect.\n");
1338 1 : con->reconnect_cnt += 1;
1339 1 : con->timeout_cnt = 0;
1340 : }
1341 : else {
1342 0 : con->status = DLT_GATEWAY_DISCONNECTED;
1343 :
1344 0 : if (dlt_event_handler_unregister_connection(&daemon_local->pEvent,
1345 : daemon_local,
1346 : receiver->fd) != 0)
1347 0 : dlt_log(LOG_ERR, "Remove passive node Connection failed\n");
1348 : }
1349 :
1350 1 : return DLT_RETURN_OK;
1351 : }
1352 :
1353 16 : while (dlt_message_read(&msg,
1354 16 : (unsigned char *)receiver->buf,
1355 16 : receiver->bytesRcvd,
1356 : 0,
1357 16 : verbose) == DLT_MESSAGE_ERROR_OK) {
1358 : DltStandardHeaderExtra *header = (DltStandardHeaderExtra *)
1359 : (msg.headerbuffer +
1360 : sizeof(DltStorageHeader) +
1361 : sizeof(DltStandardHeader));
1362 :
1363 : /* only forward messages if the received ECUid is the expected one */
1364 12 : if (strncmp(header->ecu, con->ecuid, DLT_ID_SIZE) == 0) {
1365 : uint32_t id;
1366 : uint32_t id_tmp;
1367 12 : DltPassiveControlMessage *control_msg = con->p_control_msgs;
1368 :
1369 12 : dlt_vlog(LOG_DEBUG,
1370 : "Received ECUid (%.*s) similar to configured ECUid(%s). "
1371 : "Forwarding message (%s).\n",
1372 : DLT_ID_SIZE,
1373 : header->ecu,
1374 : con->ecuid,
1375 : msg.databuffer);
1376 :
1377 12 : id_tmp = *((uint32_t *)(msg.databuffer));
1378 12 : id = DLT_ENDIAN_GET_32(msg.standardheader->htyp, id_tmp);
1379 :
1380 : /* if ID is GET_LOG_INFO, parse msg */
1381 12 : if (id == DLT_SERVICE_ID_GET_LOG_INFO) {
1382 1 : while (control_msg) {
1383 1 : if (control_msg->id == id) {
1384 1 : if (dlt_gateway_parse_get_log_info(daemon,
1385 : header->ecu,
1386 : &msg,
1387 1 : control_msg->req,
1388 : verbose) == DLT_RETURN_ERROR)
1389 1 : dlt_log(LOG_WARNING, "Parsing GET_LOG_INFO message failed!\n");
1390 :
1391 : /* Check for logstorage */
1392 1 : dlt_gateway_control_service_logstorage(daemon,
1393 : daemon_local,
1394 : verbose);
1395 :
1396 : /* initialize the flag */
1397 1 : control_msg->req = CONTROL_MESSAGE_NOT_REQUESTED;
1398 1 : break;
1399 : }
1400 :
1401 0 : control_msg = control_msg->next;
1402 : }
1403 : }
1404 11 : else if (id == DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL)
1405 : {
1406 0 : if (dlt_gateway_parse_get_default_log_level(
1407 : daemon,
1408 : daemon_local,
1409 : header->ecu,
1410 : &msg,
1411 : verbose) == DLT_RETURN_ERROR)
1412 0 : dlt_log(LOG_WARNING,
1413 : "Parsing GET_DEFAULT_LOG_LEVEL message failed!\n");
1414 : }
1415 :
1416 : /* prepare storage header */
1417 12 : if (dlt_set_storageheader(msg.storageheader,
1418 : msg.headerextra.ecu) == DLT_RETURN_ERROR) {
1419 0 : dlt_vlog(LOG_ERR, "%s: Can't set storage header\n", __func__);
1420 0 : return DLT_RETURN_ERROR;
1421 : }
1422 :
1423 12 : dlt_daemon_client_send(DLT_DAEMON_SEND_TO_ALL,
1424 : daemon,
1425 : daemon_local,
1426 : msg.headerbuffer,
1427 : sizeof(DltStorageHeader),
1428 : msg.headerbuffer + sizeof(DltStorageHeader),
1429 12 : msg.headersize - sizeof(DltStorageHeader),
1430 12 : msg.databuffer,
1431 : msg.datasize,
1432 : verbose);
1433 : } else { /* otherwise remove this connection and do not connect again */
1434 0 : dlt_vlog(LOG_WARNING,
1435 : "Received ECUid (%.*s) differs to configured ECUid(%s). "
1436 : "Discard this message.\n",
1437 : DLT_ID_SIZE,
1438 : header->ecu,
1439 : con->ecuid);
1440 :
1441 : /* disconnect from passive node */
1442 0 : con->status = DLT_GATEWAY_DISCONNECTED;
1443 0 : con->trigger = DLT_GATEWAY_DISABLED;
1444 :
1445 0 : if (dlt_event_handler_unregister_connection(&daemon_local->pEvent,
1446 : daemon_local,
1447 : receiver->fd)
1448 : != 0)
1449 0 : dlt_log(LOG_ERR, "Remove passive node Connection failed\n");
1450 :
1451 0 : dlt_log(LOG_WARNING,
1452 : "Disconnect from passive node due to invalid ECUid\n");
1453 :
1454 : /* it is possible that a partial log was received through the last recv call */
1455 : /* however, the rest will never be received since the socket will be closed by above method */
1456 : /* as such, we need to reset the receiver to prevent permanent corruption */
1457 : b_reset_receiver = true;
1458 : }
1459 :
1460 12 : if (msg.found_serialheader) {
1461 0 : if (dlt_receiver_remove(receiver,
1462 0 : msg.headersize +
1463 0 : msg.datasize -
1464 0 : sizeof(DltStorageHeader) +
1465 : sizeof(dltSerialHeader)) == -1) {
1466 : /* Return value ignored */
1467 0 : dlt_message_free(&msg, verbose);
1468 0 : return DLT_RETURN_ERROR;
1469 : }
1470 : }
1471 12 : else if (dlt_receiver_remove(receiver,
1472 12 : msg.headersize +
1473 12 : msg.datasize -
1474 : sizeof(DltStorageHeader)) == -1) {
1475 : /* Return value ignored */
1476 0 : dlt_message_free(&msg, verbose);
1477 0 : return DLT_RETURN_ERROR;
1478 : }
1479 : }
1480 :
1481 4 : if (b_reset_receiver)
1482 0 : dlt_receiver_remove(receiver, receiver->bytesRcvd);
1483 :
1484 4 : if (dlt_receiver_move_to_begin(receiver) == -1) {
1485 : /* Return value ignored */
1486 0 : dlt_message_free(&msg, verbose);
1487 0 : return DLT_RETURN_ERROR;
1488 : }
1489 :
1490 4 : if (dlt_message_free(&msg, verbose) == -1)
1491 0 : return DLT_RETURN_ERROR;
1492 :
1493 : return DLT_RETURN_OK;
1494 : }
1495 :
1496 2 : int dlt_gateway_process_gateway_timer(DltDaemon *daemon,
1497 : DltDaemonLocal *daemon_local,
1498 : DltReceiver *receiver,
1499 : int verbose)
1500 : {
1501 2 : uint64_t expir = 0;
1502 : ssize_t res = 0;
1503 :
1504 2 : PRINT_FUNCTION_VERBOSE(verbose);
1505 :
1506 2 : if ((daemon_local == NULL) || (daemon == NULL) || (receiver == NULL)) {
1507 1 : dlt_vlog(LOG_ERR,
1508 : "%s: invalid parameters\n",
1509 : __func__);
1510 1 : return DLT_RETURN_WRONG_PARAMETER;
1511 : }
1512 :
1513 1 : res = read(receiver->fd, &expir, sizeof(expir));
1514 :
1515 1 : if (res < 0)
1516 1 : dlt_vlog(LOG_WARNING,
1517 : "%s: Fail to read timer (%s)\n",
1518 : __func__,
1519 1 : strerror(errno));
1520 : /* Activity received on timer_wd, but unable to read the fd:
1521 : * let's go on sending notification */
1522 :
1523 : /* try to connect to passive nodes */
1524 1 : dlt_gateway_establish_connections(&daemon_local->pGateway,
1525 : daemon_local,
1526 : verbose);
1527 :
1528 1 : dlt_log(LOG_DEBUG, "Gateway Timer\n");
1529 :
1530 1 : return DLT_RETURN_OK;
1531 : }
1532 :
1533 0 : int dlt_gateway_forward_control_message(DltGateway *gateway,
1534 : DltDaemonLocal *daemon_local,
1535 : DltMessage *msg,
1536 : char *ecu,
1537 : int verbose)
1538 : {
1539 : int i = 0;
1540 : int ret = 0;
1541 : DltGatewayConnection *con = NULL;
1542 : uint32_t id_tmp;
1543 : uint32_t id;
1544 :
1545 0 : PRINT_FUNCTION_VERBOSE(verbose);
1546 :
1547 0 : if ((gateway == NULL) || (daemon_local == NULL) || (msg == NULL) || (ecu == NULL)) {
1548 0 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
1549 0 : return DLT_RETURN_WRONG_PARAMETER;
1550 : }
1551 :
1552 0 : for (i = 0; i < gateway->num_connections; i++)
1553 0 : if (strncmp(gateway->connections[i].ecuid,
1554 : ecu,
1555 : DLT_ID_SIZE) == 0) {
1556 : con = &gateway->connections[i];
1557 : break;
1558 : }
1559 :
1560 :
1561 :
1562 0 : if (con == NULL) {
1563 0 : dlt_log(LOG_WARNING, "Unknown passive node identifier\n");
1564 0 : return DLT_RETURN_ERROR;
1565 : }
1566 :
1567 0 : if (con->status != DLT_GATEWAY_CONNECTED) {
1568 0 : dlt_log(LOG_INFO, "Passive node is not connected\n");
1569 0 : return DLT_RETURN_ERROR;
1570 : }
1571 :
1572 0 : if (con->send_serial) { /* send serial header */
1573 0 : ret = send(con->client.sock,
1574 : (void *)dltSerialHeader,
1575 : sizeof(dltSerialHeader),
1576 : 0);
1577 :
1578 0 : if (ret == -1) {
1579 0 : dlt_log(LOG_ERR, "Sending message to passive DLT Daemon failed\n");
1580 0 : return DLT_RETURN_ERROR;
1581 : }
1582 : }
1583 :
1584 0 : ret = send(con->client.sock,
1585 : msg->headerbuffer + sizeof(DltStorageHeader),
1586 0 : msg->headersize - sizeof(DltStorageHeader),
1587 : 0);
1588 :
1589 0 : if (ret == -1) {
1590 0 : dlt_log(LOG_ERR, "Sending message to passive DLT Daemon failed\n");
1591 0 : return DLT_RETURN_ERROR;
1592 : }
1593 : else {
1594 0 : ret = send(con->client.sock, msg->databuffer, msg->datasize, 0);
1595 :
1596 0 : if (ret == -1) {
1597 0 : dlt_log(LOG_ERR, "Sending message to passive DLT Daemon failed\n");
1598 0 : return DLT_RETURN_ERROR;
1599 : }
1600 : }
1601 :
1602 0 : id_tmp = *((uint32_t *)(msg->databuffer));
1603 0 : id = DLT_ENDIAN_GET_32(msg->standardheader->htyp, id_tmp);
1604 :
1605 0 : dlt_vlog(LOG_INFO,
1606 : "Control message forwarded : %s\n",
1607 : dlt_get_service_name(id));
1608 0 : return DLT_RETURN_OK;
1609 : }
1610 :
1611 3 : int dlt_gateway_process_on_demand_request(DltGateway *gateway,
1612 : DltDaemonLocal *daemon_local,
1613 : char node_id[DLT_ID_SIZE],
1614 : int connection_status,
1615 : int verbose)
1616 : {
1617 : int i = 0;
1618 : DltGatewayConnection *con = NULL;
1619 :
1620 3 : PRINT_FUNCTION_VERBOSE(verbose);
1621 :
1622 3 : if ((gateway == NULL) || (daemon_local == NULL) || (node_id == NULL)) {
1623 1 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
1624 1 : return DLT_RETURN_WRONG_PARAMETER;
1625 : }
1626 :
1627 : /* find connection by ECU id */
1628 2 : for (i = 0; i < gateway->num_connections; i++) {
1629 2 : if (strncmp(node_id, gateway->connections[i].ecuid, DLT_ID_SIZE) == 0) {
1630 : con = &gateway->connections[i];
1631 : break;
1632 : }
1633 : }
1634 :
1635 2 : if (con == NULL) {
1636 0 : dlt_log(LOG_WARNING, "Specified ECUid not found\n");
1637 0 : return DLT_RETURN_ERROR;
1638 : }
1639 :
1640 2 : if (connection_status == 1) { /* try to connect */
1641 :
1642 2 : if (con->status != DLT_GATEWAY_CONNECTED) {
1643 1 : if (dlt_client_connect(&con->client, verbose) == 0) {
1644 : /* setup dlt connection and add to poll event loop here */
1645 0 : if (dlt_gateway_add_to_event_loop(daemon_local, con, verbose) != DLT_RETURN_OK) {
1646 0 : dlt_log(LOG_ERR, "Gateway connection creation failed\n");
1647 0 : return DLT_RETURN_ERROR;
1648 : }
1649 : }
1650 : else {
1651 1 : dlt_log(LOG_ERR, "Could not connect to passive node\n");
1652 1 : return DLT_RETURN_ERROR;
1653 : }
1654 : }
1655 : else {
1656 1 : dlt_log(LOG_INFO, "Passive node already connected\n");
1657 : }
1658 : }
1659 0 : else if (connection_status == 0) /* disconnect*/
1660 : {
1661 :
1662 0 : con->status = DLT_GATEWAY_DISCONNECTED;
1663 0 : con->trigger = DLT_GATEWAY_ON_DEMAND;
1664 :
1665 0 : if (dlt_event_handler_unregister_connection(&daemon_local->pEvent,
1666 : daemon_local,
1667 : con->client.sock) != 0)
1668 0 : dlt_log(LOG_ERR,
1669 : "Remove passive node event handler connection failed\n");
1670 : }
1671 : else {
1672 0 : dlt_log(LOG_ERR, "Unknown command (connection_status)\n");
1673 0 : return DLT_RETURN_ERROR;
1674 : }
1675 :
1676 : return DLT_RETURN_OK;
1677 : }
1678 :
1679 12 : int dlt_gateway_send_control_message(DltGatewayConnection *con,
1680 : DltPassiveControlMessage *control_msg,
1681 : void *data,
1682 : int verbose)
1683 : {
1684 : int ret = DLT_RETURN_OK;
1685 :
1686 12 : PRINT_FUNCTION_VERBOSE(verbose);
1687 :
1688 12 : if (con == NULL) {
1689 1 : dlt_vlog(LOG_WARNING,
1690 : "%s: Invalid parameter given\n",
1691 : __func__);
1692 1 : return DLT_RETURN_WRONG_PARAMETER;
1693 : }
1694 :
1695 : /* no (more) control message to be send */
1696 11 : if (control_msg->id == 0)
1697 : return DLT_RETURN_ERROR;
1698 :
1699 : /* check sendtime counter and message interval */
1700 : /* sendtime counter is 0 on startup, otherwise positive value */
1701 11 : if ((control_msg->type != CONTROL_MESSAGE_ON_DEMAND) && (con->sendtime_cnt > 0)) {
1702 0 : if (control_msg->interval <= 0)
1703 : return DLT_RETURN_ERROR;
1704 :
1705 0 : if ((control_msg->type == CONTROL_MESSAGE_PERIODIC) ||
1706 : (control_msg->type == CONTROL_MESSAGE_BOTH)) {
1707 0 : if ((con->sendtime_cnt - 1) % control_msg->interval != 0)
1708 : return DLT_RETURN_ERROR;
1709 : }
1710 : }
1711 :
1712 11 : if (con->send_serial) { /* send serial header */
1713 0 : ret = send(con->client.sock,
1714 : (void *)dltSerialHeader,
1715 : sizeof(dltSerialHeader),
1716 : 0);
1717 :
1718 0 : if (ret == -1) {
1719 0 : dlt_log(LOG_ERR, "Sending message to passive DLT Daemon failed\n");
1720 0 : return DLT_RETURN_ERROR;
1721 : }
1722 : }
1723 :
1724 11 : switch (control_msg->id) {
1725 4 : case DLT_SERVICE_ID_GET_LOG_INFO:
1726 4 : return dlt_client_get_log_info(&con->client);
1727 : break;
1728 1 : case DLT_SERVICE_ID_GET_DEFAULT_LOG_LEVEL:
1729 1 : return dlt_client_get_default_log_level(&con->client);
1730 : break;
1731 4 : case DLT_SERVICE_ID_GET_SOFTWARE_VERSION:
1732 4 : return dlt_client_get_software_version(&con->client);
1733 : break;
1734 2 : case DLT_SERVICE_ID_SET_LOG_LEVEL:
1735 :
1736 2 : if (data == NULL) {
1737 1 : dlt_vlog(LOG_WARNING,
1738 : "Insufficient data for %s received. Send control request failed.\n",
1739 : dlt_get_service_name(control_msg->id));
1740 1 : return DLT_RETURN_ERROR;
1741 : }
1742 :
1743 : DltServiceSetLogLevel *req = (DltServiceSetLogLevel *)data;
1744 1 : return dlt_client_send_log_level(&con->client,
1745 1 : req->apid,
1746 1 : req->ctid,
1747 1 : req->log_level);
1748 : break;
1749 0 : default:
1750 0 : dlt_vlog(LOG_WARNING,
1751 : "Cannot forward request: %s.\n",
1752 : dlt_get_service_name(control_msg->id));
1753 : }
1754 :
1755 0 : return DLT_RETURN_OK;
1756 : }
1757 :
1758 0 : DltGatewayConnection *dlt_gateway_get_connection(DltGateway *gateway,
1759 : char *ecu,
1760 : int verbose)
1761 : {
1762 : DltGatewayConnection *con = NULL;
1763 : int i = 0;
1764 :
1765 0 : PRINT_FUNCTION_VERBOSE(verbose);
1766 :
1767 0 : if ((gateway == NULL) || (ecu == NULL)) {
1768 0 : dlt_vlog(LOG_ERR, "%s: wrong parameter\n", __func__);
1769 0 : return con;
1770 : }
1771 :
1772 0 : for (i = 0; i < gateway->num_connections; i++) {
1773 0 : con = &gateway->connections[i];
1774 :
1775 0 : if (strncmp(con->ecuid, ecu, DLT_ID_SIZE) == 0)
1776 0 : return con;
1777 : }
1778 :
1779 0 : dlt_vlog(LOG_ERR, "%s: No connection found\n", ecu);
1780 :
1781 0 : return con;
1782 : }
|