LCOV - code coverage report
Current view: top level - gateway - dlt_gateway.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 49.9 % 690 344
Test Date: 2026-08-27 10:11:10 Functions: 71.0 % 31 22

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

Generated by: LCOV version 2.0-1