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.6 % 57 30
Test Date: 2026-08-27 10:11:10 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            1 : int dlt_daemon_socket_open(int* sock, unsigned int servPort, char* ip)
      69              : {
      70            1 :     int yes = 1;
      71              :     int ret_inet_pton = 1;
      72              :     int lastErrno = 0;
      73              : 
      74              : #ifdef DLT_USE_IPv6
      75              : 
      76              :     /* create socket */
      77            1 :     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, strerror(lastErrno));
      80            0 :         return -1;
      81              :     }
      82              : 
      83              : #else
      84              : 
      85              :     if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
      86              :         lastErrno = errno;
      87              :         dlt_vlog(LOG_ERR, "dlt_daemon_socket_open: socket() error %d: %s\n", lastErrno, strerror(lastErrno));
      88              :         return -1;
      89              :     }
      90              : 
      91              : #endif
      92              : 
      93            1 :     dlt_vlog(LOG_INFO, "%s: Socket created\n", __func__);
      94              : 
      95              :     /* setsockpt SO_REUSEADDR */
      96            1 :     if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
      97            0 :         lastErrno = errno;
      98            0 :         dlt_vlog(
      99              :             LOG_ERR, "dlt_daemon_socket_open: Setsockopt error %d in dlt_daemon_local_connection_init: %s\n", lastErrno,
     100              :             strerror(lastErrno));
     101            0 :         return -1;
     102              :     }
     103              : 
     104              :     /* bind */
     105              : #ifdef DLT_USE_IPv6
     106              :     struct sockaddr_in6 forced_addr;
     107              :     memset(&forced_addr, 0, sizeof(forced_addr));
     108            1 :     forced_addr.sin6_family = AF_INET6;
     109            1 :     forced_addr.sin6_port = htons(servPort);
     110              : 
     111            1 :     if (0 == strcmp(ip, "0.0.0.0")) {
     112            1 :         forced_addr.sin6_addr = in6addr_any;
     113              :     } else {
     114            0 :         ret_inet_pton = inet_pton(AF_INET6, ip, &forced_addr.sin6_addr);
     115              :     }
     116              : 
     117              : #else
     118              :     struct sockaddr_in forced_addr;
     119              :     memset(&forced_addr, 0, sizeof(forced_addr));
     120              :     forced_addr.sin_family = AF_INET;
     121              :     forced_addr.sin_port = htons(servPort);
     122              :     ret_inet_pton = inet_pton(AF_INET, ip, &forced_addr.sin_addr);
     123              : #endif
     124              : 
     125              :     /* inet_pton returns 1 on success */
     126            0 :     if (ret_inet_pton != 1) {
     127            0 :         lastErrno = errno;
     128            0 :         dlt_vlog(
     129              :             LOG_WARNING, "dlt_daemon_socket_open: inet_pton() error %d: %s. Cannot convert IP address: %s\n", lastErrno,
     130              :             strerror(lastErrno), ip);
     131            0 :         return -1;
     132              :     }
     133              : 
     134            1 :     if (bind(*sock, (struct sockaddr*)&forced_addr, sizeof(forced_addr)) == -1) {
     135            0 :         lastErrno = errno; /*close() may set errno too */
     136            0 :         close(*sock);
     137            0 :         dlt_vlog(LOG_WARNING, "dlt_daemon_socket_open: bind() error %d: %s\n", lastErrno, strerror(lastErrno));
     138            0 :         return -1;
     139              :     }
     140              : 
     141              :     /*listen */
     142            1 :     dlt_vlog(LOG_INFO, "%s: Listening on ip %s and port: %u\n", __func__, ip, servPort);
     143              : 
     144              :     /* get socket buffer size */
     145            1 :     dlt_vlog(
     146              :         LOG_INFO, "dlt_daemon_socket_open: Socket send queue size: %d\n",
     147              :         dlt_daemon_socket_get_send_qeue_max_size(*sock));
     148              : 
     149            1 :     if (listen(*sock, 3) < 0) {
     150            0 :         lastErrno = errno;
     151            0 :         dlt_vlog(
     152              :             LOG_WARNING, "dlt_daemon_socket_open: listen() failed with error %d: %s\n", lastErrno, strerror(lastErrno));
     153            0 :         return -1;
     154              :     }
     155              : 
     156              :     return 0; /* OK */
     157              : }
     158              : 
     159            0 : int dlt_daemon_socket_close(int sock)
     160              : {
     161            0 :     close(sock);
     162              : 
     163            0 :     return 0;
     164              : }
     165              : 
     166            1 : int dlt_daemon_socket_send(int sock, void* data1, int size1, void* data2, int size2, char serialheader)
     167              : {
     168              :     int ret = DLT_RETURN_OK;
     169              : 
     170              :     /* Optional: Send serial header, if requested */
     171            1 :     if (serialheader) {
     172            0 :         ret = dlt_daemon_socket_sendreliable(sock, dltSerialHeader, sizeof(dltSerialHeader));
     173              : 
     174            0 :         if (ret != DLT_RETURN_OK) {
     175              :             return ret;
     176              :         }
     177              :     }
     178              : 
     179              :     /* Send data */
     180            1 :     if ((data1 != NULL) && (size1 > 0)) {
     181            1 :         ret = dlt_daemon_socket_sendreliable(sock, data1, size1);
     182              : 
     183            1 :         if (ret != DLT_RETURN_OK) {
     184              :             return ret;
     185              :         }
     186              :     }
     187              : 
     188            1 :     if ((data2 != NULL) && (size2 > 0)) {
     189            1 :         ret = dlt_daemon_socket_sendreliable(sock, data2, size2);
     190              :     }
     191              : 
     192              :     return ret;
     193              : }
     194              : 
     195            1 : int dlt_daemon_socket_get_send_qeue_max_size(int sock)
     196              : {
     197            1 :     int n = 0;
     198            1 :     socklen_t m = sizeof(n);
     199            1 :     if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&n, &m) < 0) {
     200            0 :         dlt_vlog(LOG_ERR, "%s: socket get failed!\n", __func__);
     201            0 :         return -errno;
     202              :     }
     203              : 
     204            1 :     return n;
     205              : }
     206              : 
     207            8 : int dlt_daemon_socket_sendreliable(int sock, const void* data_buffer, int message_size)
     208              : {
     209              :     int data_sent = 0;
     210              : 
     211           16 :     while (data_sent < message_size) {
     212            8 :         ssize_t ret = send(sock, (const uint8_t*)data_buffer + data_sent, (size_t)(message_size - data_sent), 0);
     213              : 
     214            8 :         if (ret < 0) {
     215            0 :             dlt_vlog(LOG_WARNING, "%s: socket send failed [errno: %d]!\n", __func__, errno);
     216              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
     217              :             /* notify systemd here that we are still alive
     218              :              * otherwise we might miss notifying the watchdog when
     219              :              * the watchdog interval is small and multiple timeouts occur back to back
     220              :              */
     221              :             if (sd_notify(0, "WATCHDOG=1") < 0)
     222              :                 dlt_vlog(LOG_WARNING, "%s: Could not reset systemd watchdog\n", __func__);
     223              : #endif
     224            0 :             return DLT_DAEMON_ERROR_SEND_FAILED;
     225              :         } else {
     226            8 :             data_sent += ret;
     227              :         }
     228              :     }
     229              : 
     230              :     return DLT_DAEMON_ERROR_OK;
     231              : }
        

Generated by: LCOV version 2.0-1