LCOV - code coverage report
Current view: top level - daemon - dlt_daemon_socket.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 52.5 % 59 31
Test Date: 2025-12-12 09:13:23 Functions: 80.0 % 5 4

            Line data    Source code
       1              : /*
       2              :  * SPDX license identifier: MPL-2.0
       3              :  *
       4              :  * Copyright (C) 2011-2015, BMW AG
       5              :  *
       6              :  * This file is part of COVESA Project DLT - Diagnostic Log and Trace.
       7              :  *
       8              :  * This Source Code Form is subject to the terms of the
       9              :  * Mozilla Public License (MPL), v. 2.0.
      10              :  * If a copy of the MPL was not distributed with this file,
      11              :  * You can obtain one at http://mozilla.org/MPL/2.0/.
      12              :  *
      13              :  * For further information see http://www.covesa.org/.
      14              :  */
      15              : 
      16              : /*!
      17              :  * \author
      18              :  * Alexander Wenzel <alexander.aw.wenzel@bmw.de>
      19              :  * Markus Klein <Markus.Klein@esk.fraunhofer.de>
      20              :  * Mikko Rapeli <mikko.rapeli@bmw.de>
      21              :  *
      22              :  * \copyright Copyright © 2011-2015 BMW AG. \n
      23              :  * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
      24              :  *
      25              :  * \file dlt_daemon_socket.c
      26              :  */
      27              : 
      28              : 
      29              : #include <netdb.h>
      30              : #include <ctype.h>
      31              : #include <stdio.h>      /* for printf() and fprintf() */
      32              : #include <sys/socket.h> /* for socket(), connect(), (), and recv() */
      33              : 
      34              : #pragma GCC diagnostic ignored "-Wconversion"
      35              : #include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
      36              : #pragma GCC diagnostic push
      37              : #pragma GCC diagnostic pop
      38              : 
      39              : #include <stdlib.h>     /* for atoi() and exit() */
      40              : #include <string.h>     /* for memset() */
      41              : #include <unistd.h>     /* for close() */
      42              : #include <signal.h>
      43              : #include <syslog.h>
      44              : #include <errno.h>
      45              : #include <pthread.h>
      46              : #include <sys/ioctl.h>
      47              : 
      48              : #ifdef linux
      49              : #include <sys/timerfd.h>
      50              : #endif
      51              : #include <sys/time.h>
      52              : #if defined(linux) && defined(__NR_statx)
      53              : #include <linux/stat.h>
      54              : #endif
      55              : 
      56              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
      57              : #include <systemd/sd-daemon.h>
      58              : #endif
      59              : 
      60              : #include "dlt_types.h"
      61              : #include "dlt_log.h"
      62              : #include "dlt-daemon.h"
      63              : #include "dlt-daemon_cfg.h"
      64              : #include "dlt_daemon_common_cfg.h"
      65              : 
      66              : #include "dlt_daemon_socket.h"
      67              : 
      68            9 : int dlt_daemon_socket_open(int *sock, unsigned int servPort, char *ip)
      69              : {
      70            9 :     int yes = 1;
      71              :     int ret_inet_pton = 1;
      72              :     int lastErrno = 0;
      73              : 
      74              : #ifdef DLT_USE_IPv6
      75              : 
      76              :     /* create socket */
      77            9 :     if ((*sock = socket(AF_INET6, SOCK_STREAM, 0)) == -1) {
      78            0 :         lastErrno = errno;
      79            0 :         dlt_vlog(LOG_ERR, "dlt_daemon_socket_open: socket() error %d: %s\n", lastErrno,
      80              :                  strerror(lastErrno));
      81            0 :         return -1;
      82              :     }
      83              : 
      84              : #else
      85              : 
      86              :     if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
      87              :         lastErrno = errno;
      88              :         dlt_vlog(LOG_ERR, "dlt_daemon_socket_open: socket() error %d: %s\n", lastErrno,
      89              :                  strerror(lastErrno));
      90              :         return -1;
      91              :     }
      92              : 
      93              : #endif
      94              : 
      95            9 :     dlt_vlog(LOG_INFO, "%s: Socket created\n", __func__);
      96              : 
      97              :     /* setsockpt SO_REUSEADDR */
      98            9 :     if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
      99            0 :         lastErrno = errno;
     100            0 :         dlt_vlog(
     101              :             LOG_ERR,
     102              :             "dlt_daemon_socket_open: Setsockopt error %d in dlt_daemon_local_connection_init: %s\n",
     103              :             lastErrno,
     104              :             strerror(lastErrno));
     105            0 :         return -1;
     106              :     }
     107              : 
     108              :     /* bind */
     109              : #ifdef DLT_USE_IPv6
     110              :     struct sockaddr_in6 forced_addr;
     111              :     memset(&forced_addr, 0, sizeof(forced_addr));
     112            9 :     forced_addr.sin6_family = AF_INET6;
     113            9 :     forced_addr.sin6_port = htons(servPort);
     114              : 
     115            9 :     if (0 == strcmp(ip, "0.0.0.0")) {
     116            9 :         forced_addr.sin6_addr = in6addr_any;
     117              :     } else {
     118            0 :         ret_inet_pton = inet_pton(AF_INET6, ip, &forced_addr.sin6_addr);
     119              :     }
     120              : 
     121              : #else
     122              :     struct sockaddr_in forced_addr;
     123              :     memset(&forced_addr, 0, sizeof(forced_addr));
     124              :     forced_addr.sin_family = AF_INET;
     125              :     forced_addr.sin_port = htons(servPort);
     126              :     ret_inet_pton = inet_pton(AF_INET, ip, &forced_addr.sin_addr);
     127              : #endif
     128              : 
     129              :     /* inet_pton returns 1 on success */
     130            0 :     if (ret_inet_pton != 1) {
     131            0 :         lastErrno = errno;
     132            0 :         dlt_vlog(
     133              :             LOG_WARNING,
     134              :             "dlt_daemon_socket_open: inet_pton() error %d: %s. Cannot convert IP address: %s\n",
     135              :             lastErrno,
     136              :             strerror(lastErrno),
     137              :             ip);
     138            0 :         return -1;
     139              :     }
     140              : 
     141            9 :     if (bind(*sock, (struct sockaddr *)&forced_addr, sizeof(forced_addr)) == -1) {
     142            0 :         lastErrno = errno;     /*close() may set errno too */
     143            0 :         close(*sock);
     144            0 :         dlt_vlog(LOG_WARNING, "dlt_daemon_socket_open: bind() error %d: %s\n", lastErrno,
     145              :                  strerror(lastErrno));
     146            0 :         return -1;
     147              :     }
     148              : 
     149              :     /*listen */
     150            9 :     dlt_vlog(LOG_INFO, "%s: Listening on ip %s and port: %u\n", __func__, ip, servPort);
     151              : 
     152              :     /* get socket buffer size */
     153            9 :     dlt_vlog(LOG_INFO, "dlt_daemon_socket_open: Socket send queue size: %d\n",
     154              :              dlt_daemon_socket_get_send_qeue_max_size(*sock));
     155              : 
     156            9 :     if (listen(*sock, 3) < 0) {
     157            0 :         lastErrno = errno;
     158            0 :         dlt_vlog(LOG_WARNING,
     159              :                  "dlt_daemon_socket_open: listen() failed with error %d: %s\n",
     160              :                  lastErrno,
     161              :                  strerror(lastErrno));
     162            0 :         return -1;
     163              :     }
     164              : 
     165              :     return 0; /* OK */
     166              : }
     167              : 
     168            0 : int dlt_daemon_socket_close(int sock)
     169              : {
     170            0 :     close(sock);
     171              : 
     172            0 :     return 0;
     173              : }
     174              : 
     175           16 : int dlt_daemon_socket_send(int sock,
     176              :                            void *data1,
     177              :                            int size1,
     178              :                            void *data2,
     179              :                            int size2,
     180              :                            char serialheader)
     181              : {
     182              :     int ret = DLT_RETURN_OK;
     183              : 
     184              :     /* Optional: Send serial header, if requested */
     185           16 :     if (serialheader) {
     186            0 :         ret = dlt_daemon_socket_sendreliable(sock,
     187              :                                              dltSerialHeader,
     188              :                                              sizeof(dltSerialHeader));
     189              : 
     190            0 :         if (ret != DLT_RETURN_OK) {
     191              :             return ret;
     192              :         }
     193              :     }
     194              : 
     195              :     /* Send data */
     196           16 :     if ((data1 != NULL) && (size1 > 0)) {
     197           16 :         ret = dlt_daemon_socket_sendreliable(sock, data1, size1);
     198              : 
     199           16 :         if (ret != DLT_RETURN_OK) {
     200              :             return ret;
     201              :         }
     202              :     }
     203              : 
     204           16 :     if ((data2 != NULL) && (size2 > 0)) {
     205           16 :         ret = dlt_daemon_socket_sendreliable(sock, data2, size2);
     206              :     }
     207              : 
     208              :     return ret;
     209              : }
     210              : 
     211            9 : int dlt_daemon_socket_get_send_qeue_max_size(int sock)
     212              : {
     213            9 :     int n = 0;
     214            9 :     socklen_t m = sizeof(n);
     215            9 :     if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&n, &m) < 0) {
     216            0 :         dlt_vlog(LOG_ERR,
     217              :                  "%s: socket get failed!\n", __func__);
     218            0 :         return -errno;
     219              :     }
     220              : 
     221            9 :     return n;
     222              : }
     223              : 
     224          466 : int dlt_daemon_socket_sendreliable(int sock, const void *data_buffer, int message_size)
     225              : {
     226              :     int data_sent = 0;
     227              : 
     228          932 :     while (data_sent < message_size) {
     229          466 :         ssize_t ret = send(sock,
     230              :                            (const uint8_t *)data_buffer + data_sent,
     231          466 :                            (size_t)(message_size - data_sent),
     232              :                            0);
     233              : 
     234          466 :         if (ret < 0) {
     235            0 :             dlt_vlog(LOG_WARNING,
     236            0 :                      "%s: socket send failed [errno: %d]!\n", __func__, errno);
     237              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
     238              :             /* notify systemd here that we are still alive
     239              :              * otherwise we might miss notifying the watchdog when
     240              :              * the watchdog interval is small and multiple timeouts occur back to back
     241              :              */
     242              :             if (sd_notify(0, "WATCHDOG=1") < 0)
     243              :                 dlt_vlog(LOG_WARNING, "%s: Could not reset systemd watchdog\n", __func__);
     244              : #endif
     245            0 :             return DLT_DAEMON_ERROR_SEND_FAILED;
     246              :         } else {
     247          466 :             data_sent += ret;
     248              :         }
     249              :     }
     250              : 
     251              :     return DLT_DAEMON_ERROR_OK;
     252              : }
        

Generated by: LCOV version 2.0-1