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-03-25 20:53:42 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              : #include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
      34              : #include <stdlib.h>     /* for atoi() and exit() */
      35              : #include <string.h>     /* for memset() */
      36              : #include <unistd.h>     /* for close() */
      37              : #include <signal.h>
      38              : #include <syslog.h>
      39              : #include <errno.h>
      40              : #include <pthread.h>
      41              : #include <sys/ioctl.h>
      42              : 
      43              : #ifdef linux
      44              : #include <sys/timerfd.h>
      45              : #endif
      46              : #include <sys/time.h>
      47              : #if defined(linux) && defined(__NR_statx)
      48              : #include <linux/stat.h>
      49              : #endif
      50              : 
      51              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
      52              : #include <systemd/sd-daemon.h>
      53              : #endif
      54              : 
      55              : #include "dlt_types.h"
      56              : #include "dlt_log.h"
      57              : #include "dlt-daemon.h"
      58              : #include "dlt-daemon_cfg.h"
      59              : #include "dlt_daemon_common_cfg.h"
      60              : 
      61              : #include "dlt_daemon_socket.h"
      62              : 
      63            9 : int dlt_daemon_socket_open(int *sock, unsigned int servPort, char *ip)
      64              : {
      65            9 :     int yes = 1;
      66              :     int ret_inet_pton = 1;
      67              :     int lastErrno = 0;
      68              : 
      69              : #ifdef DLT_USE_IPv6
      70              : 
      71              :     /* create socket */
      72            9 :     if ((*sock = socket(AF_INET6, SOCK_STREAM, 0)) == -1) {
      73            0 :         lastErrno = errno;
      74            0 :         dlt_vlog(LOG_ERR, "dlt_daemon_socket_open: socket() error %d: %s\n", lastErrno,
      75              :                  strerror(lastErrno));
      76            0 :         return -1;
      77              :     }
      78              : 
      79              : #else
      80              : 
      81              :     if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
      82              :         lastErrno = errno;
      83              :         dlt_vlog(LOG_ERR, "dlt_daemon_socket_open: socket() error %d: %s\n", lastErrno,
      84              :                  strerror(lastErrno));
      85              :         return -1;
      86              :     }
      87              : 
      88              : #endif
      89              : 
      90            9 :     dlt_vlog(LOG_INFO, "%s: Socket created\n", __FUNCTION__);
      91              : 
      92              :     /* setsockpt SO_REUSEADDR */
      93            9 :     if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
      94            0 :         lastErrno = errno;
      95            0 :         dlt_vlog(
      96              :             LOG_ERR,
      97              :             "dlt_daemon_socket_open: Setsockopt error %d in dlt_daemon_local_connection_init: %s\n",
      98              :             lastErrno,
      99              :             strerror(lastErrno));
     100            0 :         return -1;
     101              :     }
     102              : 
     103              :     /* bind */
     104              : #ifdef DLT_USE_IPv6
     105              :     struct sockaddr_in6 forced_addr;
     106              :     memset(&forced_addr, 0, sizeof(forced_addr));
     107            9 :     forced_addr.sin6_family = AF_INET6;
     108            9 :     forced_addr.sin6_port = htons(servPort);
     109              : 
     110            9 :     if (0 == strcmp(ip, "0.0.0.0")) {
     111            9 :         forced_addr.sin6_addr = in6addr_any;
     112              :     } else {
     113            0 :         ret_inet_pton = inet_pton(AF_INET6, ip, &forced_addr.sin6_addr);
     114              :     }
     115              : 
     116              : #else
     117              :     struct sockaddr_in forced_addr;
     118              :     memset(&forced_addr, 0, sizeof(forced_addr));
     119              :     forced_addr.sin_family = AF_INET;
     120              :     forced_addr.sin_port = htons(servPort);
     121              :     ret_inet_pton = inet_pton(AF_INET, ip, &forced_addr.sin_addr);
     122              : #endif
     123              : 
     124              :     /* inet_pton returns 1 on success */
     125            0 :     if (ret_inet_pton != 1) {
     126            0 :         lastErrno = errno;
     127            0 :         dlt_vlog(
     128              :             LOG_WARNING,
     129              :             "dlt_daemon_socket_open: inet_pton() error %d: %s. Cannot convert IP address: %s\n",
     130              :             lastErrno,
     131              :             strerror(lastErrno),
     132              :             ip);
     133            0 :         return -1;
     134              :     }
     135              : 
     136            9 :     if (bind(*sock, (struct sockaddr *)&forced_addr, sizeof(forced_addr)) == -1) {
     137            0 :         lastErrno = errno;     /*close() may set errno too */
     138            0 :         close(*sock);
     139            0 :         dlt_vlog(LOG_WARNING, "dlt_daemon_socket_open: bind() error %d: %s\n", lastErrno,
     140              :                  strerror(lastErrno));
     141            0 :         return -1;
     142              :     }
     143              : 
     144              :     /*listen */
     145            9 :     dlt_vlog(LOG_INFO, "%s: Listening on ip %s and port: %u\n", __FUNCTION__, ip, servPort);
     146              : 
     147              :     /* get socket buffer size */
     148            9 :     dlt_vlog(LOG_INFO, "dlt_daemon_socket_open: Socket send queue size: %d\n",
     149              :              dlt_daemon_socket_get_send_qeue_max_size(*sock));
     150              : 
     151            9 :     if (listen(*sock, 3) < 0) {
     152            0 :         lastErrno = errno;
     153            0 :         dlt_vlog(LOG_WARNING,
     154              :                  "dlt_daemon_socket_open: listen() failed with error %d: %s\n",
     155              :                  lastErrno,
     156              :                  strerror(lastErrno));
     157            0 :         return -1;
     158              :     }
     159              : 
     160              :     return 0; /* OK */
     161              : }
     162              : 
     163            0 : int dlt_daemon_socket_close(int sock)
     164              : {
     165            0 :     close(sock);
     166              : 
     167            0 :     return 0;
     168              : }
     169              : 
     170           16 : int dlt_daemon_socket_send(int sock,
     171              :                            void *data1,
     172              :                            int size1,
     173              :                            void *data2,
     174              :                            int size2,
     175              :                            char serialheader)
     176              : {
     177              :     int ret = DLT_RETURN_OK;
     178              : 
     179              :     /* Optional: Send serial header, if requested */
     180           16 :     if (serialheader) {
     181            0 :         ret = dlt_daemon_socket_sendreliable(sock,
     182              :                                              (void *)dltSerialHeader,
     183              :                                              sizeof(dltSerialHeader));
     184              : 
     185            0 :         if (ret != DLT_RETURN_OK) {
     186              :             return ret;
     187              :         }
     188              :     }
     189              : 
     190              :     /* Send data */
     191           16 :     if ((data1 != NULL) && (size1 > 0)) {
     192           16 :         ret = dlt_daemon_socket_sendreliable(sock, data1, size1);
     193              : 
     194           16 :         if (ret != DLT_RETURN_OK) {
     195              :             return ret;
     196              :         }
     197              :     }
     198              : 
     199           16 :     if ((data2 != NULL) && (size2 > 0)) {
     200           16 :         ret = dlt_daemon_socket_sendreliable(sock, data2, size2);
     201              :     }
     202              : 
     203              :     return ret;
     204              : }
     205              : 
     206            9 : int dlt_daemon_socket_get_send_qeue_max_size(int sock)
     207              : {
     208            9 :     int n = 0;
     209            9 :     socklen_t m = sizeof(n);
     210            9 :     if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&n, &m) < 0) {
     211            0 :         dlt_vlog(LOG_ERR,
     212              :                  "%s: socket get failed!\n", __func__);
     213            0 :         return -errno;
     214              :     }
     215              : 
     216            9 :     return n;
     217              : }
     218              : 
     219          466 : int dlt_daemon_socket_sendreliable(int sock, void *data_buffer, int message_size)
     220              : {
     221              :     int data_sent = 0;
     222              : 
     223          932 :     while (data_sent < message_size) {
     224          466 :         ssize_t ret = send(sock,
     225              :                            (uint8_t *)data_buffer + data_sent,
     226          466 :                            message_size - data_sent,
     227              :                            0);
     228              : 
     229          466 :         if (ret < 0) {
     230            0 :             dlt_vlog(LOG_WARNING,
     231            0 :                      "%s: socket send failed [errno: %d]!\n", __func__, errno);
     232              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
     233              :             /* notify systemd here that we are still alive
     234              :              * otherwise we might miss notifying the watchdog when
     235              :              * the watchdog interval is small and multiple timeouts occur back to back
     236              :              */
     237              :             if (sd_notify(0, "WATCHDOG=1") < 0)
     238              :                 dlt_vlog(LOG_WARNING, "%s: Could not reset systemd watchdog\n", __func__);
     239              : #endif
     240            0 :             return DLT_DAEMON_ERROR_SEND_FAILED;
     241              :         } else {
     242          466 :             data_sent += ret;
     243              :         }
     244              :     }
     245              : 
     246              :     return DLT_DAEMON_ERROR_OK;
     247              : }
        

Generated by: LCOV version 2.0-1