/* * Copyright (c) 2019 LG Electronics Inc. * SPDX-License-Identifier: MPL-2.0 * * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.genivi.org/. */ /*! * \author * Guruprasad KN * Sachin Sudhakar Shetty * Sunil Kovila Sampath * * \Copyright (c) 2019 LG Electronics Inc. * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_daemon_udp_socket.c */ #include "dlt_daemon_udp_common_socket.h" static void dlt_daemon_udp_clientmsg_send(DltDaemonClientSockInfo *clientinfo, void *data1, int size1, void *data2, int size2, int verbose); static int g_udp_sock_fd = -1; static DltDaemonClientSockInfo g_udpmulticast_addr; /* ************************************************************************** */ /* Function : dlt_daemon_udp_init_clientstruct */ /* In Param : UDP client_info struct to be initilzed */ /* Out Param : NIL */ /* Description: client struct to be initilized to copy control/connect/disconnect */ /* client addr */ /* ************************************************************************** */ void dlt_daemon_udp_init_clientstruct(DltDaemonClientSockInfo *clientinfo_struct) { if (clientinfo_struct == NULL) { dlt_vlog(LOG_ERR, "%s: NULL arg\n", __func__); return; } memset(&clientinfo_struct->clientaddr, 0x00, sizeof(clientinfo_struct->clientaddr)); clientinfo_struct->clientaddr_size = sizeof(clientinfo_struct->clientaddr); clientinfo_struct->isvalidflag = ADDRESS_INVALID; /* info is invalid */ dlt_vlog(LOG_DEBUG, "%s: client addr struct init success \n", __func__); dlt_log(LOG_INFO, "dlt_daemon_udp_init_clientstruct: client addr struct init success \n"); } /* ************************************************************************** */ /* Function : dlt_daemon_udp_setmulticast_addr */ /* In Param : NIL */ /* Out Param : NIL */ /* Description: set the multicast addr to global variables */ /* ************************************************************************** */ void dlt_daemon_udp_setmulticast_addr(DltDaemonLocal *daemon_local) { if (daemon_local == NULL) { dlt_vlog(LOG_ERR, "%s: NULL arg\n", __func__); return; } dlt_daemon_udp_init_clientstruct(&g_udpmulticast_addr); struct sockaddr_in clientaddr; clientaddr.sin_family = AF_INET; inet_pton(AF_INET, daemon_local->UDPMulticastIPAddress, &clientaddr.sin_addr); clientaddr.sin_port = htons(daemon_local->UDPMulticastIPPort); memcpy(&g_udpmulticast_addr.clientaddr, &clientaddr, sizeof(struct sockaddr_in)); g_udpmulticast_addr.clientaddr_size = sizeof(g_udpmulticast_addr.clientaddr); g_udpmulticast_addr.isvalidflag = ADDRESS_VALID; } /* ************************************************************************** */ /* Function : dlt_daemon_udp_connection_setup */ /* In Param : contains daemon param values used globally */ /* Out Param : status of udp connection setup and fd registration */ /* Description: DataGram socket fd connection is setup */ /* fd is registered with the epoll */ /* ************************************************************************** */ DltReturnValue dlt_daemon_udp_connection_setup(DltDaemonLocal *daemon_local) { int fd = DLT_FD_INIT; DltReturnValue ret_val = DLT_RETURN_WRONG_PARAMETER; if (daemon_local == NULL) return ret_val; if ((ret_val = dlt_daemon_udp_socket_open(&fd, daemon_local->flags.port)) != DLT_RETURN_OK) { dlt_log(LOG_ERR, "Could not initialize udp socket.\n"); } else { /* assign to global udp fd */ g_udp_sock_fd = fd; /* set global multicast addr */ dlt_daemon_udp_setmulticast_addr(daemon_local); dlt_log(LOG_DEBUG, "initialize udp socket success\n"); } return ret_val; } /* ************************************************************************** */ /* Function : dlt_daemon_udp_socket_open */ /* In Param : contains udp port number */ /* Out Param : status of udp connection setup */ /* Description: This funtion is used to setup DGRAM connection */ /* does socket()->bind() on udp port */ /* ************************************************************************** */ DltReturnValue dlt_daemon_udp_socket_open(int *sock, unsigned int servPort) { int enable_reuse_addr = 1; int sockbuffer = DLT_DAEMON_RCVBUFSIZESOCK; char portnumbuffer[SOCKPORT_MAX_LEN] = { 0 }; struct addrinfo hints; struct addrinfo *servinfo = NULL; struct addrinfo *addrinfo_iterator = NULL; int getaddrinfo_errorcode = -1; if (sock == NULL) return DLT_RETURN_WRONG_PARAMETER; memset(&hints, 0, sizeof hints); #ifdef DLT_USE_IPv6 hints.ai_family = AF_INET6; /* force IPv6 - will still work with IPv4 */ #else hints.ai_family = AF_INET; #endif hints.ai_socktype = SOCK_DGRAM;/* UDP Connection */ hints.ai_flags = AI_PASSIVE; /* use my IP address */ snprintf(portnumbuffer, SOCKPORT_MAX_LEN, "%d", servPort); if ((getaddrinfo_errorcode = getaddrinfo(NULL, portnumbuffer, &hints, &servinfo)) != 0) { dlt_vlog(LOG_WARNING, "[%s:%d] getaddrinfo: %s\n", __func__, __LINE__, gai_strerror(getaddrinfo_errorcode)); return DLT_RETURN_ERROR; } for (addrinfo_iterator = servinfo; addrinfo_iterator != NULL; addrinfo_iterator = addrinfo_iterator->ai_next) { if ((*sock = socket(addrinfo_iterator->ai_family, addrinfo_iterator->ai_socktype, addrinfo_iterator->ai_protocol)) == SYSTEM_CALL_ERROR) { dlt_log(LOG_WARNING, "socket() error\n"); continue; } dlt_vlog(LOG_INFO, "[%s:%d] Socket created - socket_family:%i socket_type:%i, protocol:%i\n", __func__, __LINE__, addrinfo_iterator->ai_family, addrinfo_iterator->ai_socktype, addrinfo_iterator->ai_protocol); if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &enable_reuse_addr, sizeof(enable_reuse_addr)) == SYSTEM_CALL_ERROR) { dlt_vlog(LOG_WARNING, "[%s:%d] Setsockopt error %s\n", __func__, __LINE__, strerror(errno)); close(*sock); continue; } if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUF, &sockbuffer, sizeof(sockbuffer)) == SYSTEM_CALL_ERROR) { dlt_vlog(LOG_WARNING, "[%s:%d] Setsockopt error %s\n", __func__, __LINE__, strerror(errno)); close(*sock); continue; } if (bind(*sock, addrinfo_iterator->ai_addr, addrinfo_iterator->ai_addrlen) == SYSTEM_CALL_ERROR) { close(*sock); dlt_log(LOG_WARNING, "bind() error\n"); continue; } break; } if (addrinfo_iterator == NULL) { dlt_log(LOG_WARNING, "failed to bind socket\n"); return DLT_RETURN_ERROR; } freeaddrinfo(servinfo); return DLT_RETURN_OK; /* OK */ } /* ************************************************************************** */ /* Function : dlt_daemon_udp_dltmsg_multicast */ /* In Param : data bytes in dlt format */ /* Out Param : NIL */ /* Description: multicast UDP dlt-message packets to dlt-client */ /* ************************************************************************** */ void dlt_daemon_udp_dltmsg_multicast(void *data1, int size1, void *data2, int size2, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); /* * When UDP Buffer is implemented then data2 would be expected to be NULL * as the data comes from buffer directly. In that case data2 should * not be checked for NULL */ if ((data1 == NULL) || (data2 == NULL)) { dlt_vlog(LOG_ERR, "%s: NULL arg\n", __func__); return; } dlt_daemon_udp_clientmsg_send(&g_udpmulticast_addr, data1, size1, data2, size2, verbose); } /* ************************************************************************** */ /* Function : dlt_daemon_udp_clientmsg_send */ /* In Param : data bytes & respective size in dlt format */ /* Out Param : NIL */ /* Description: common interface to send data via UDP protocol */ /* ************************************************************************** */ void dlt_daemon_udp_clientmsg_send(DltDaemonClientSockInfo *clientinfo, void *data1, int size1, void *data2, int size2, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); if ((clientinfo->isvalidflag == ADDRESS_VALID) && (size1 > 0) && (size2 > 0)) { void *data = (void *)calloc(size1 + size2, sizeof(char)); if (data == NULL) { dlt_vlog(LOG_ERR, "%s: calloc failure\n", __func__); return; } memcpy(data, data1, size1); memcpy(data + size1, data2, size2); if (sendto(g_udp_sock_fd, data, size1 + size2, 0, (struct sockaddr *)&clientinfo->clientaddr, clientinfo->clientaddr_size) < 0) dlt_vlog(LOG_ERR, "%s: Send UDP Packet Data failed\n", __func__); free(data); data = NULL; } else { if (clientinfo->isvalidflag != ADDRESS_VALID) dlt_vlog(LOG_ERR, "%s: clientinfo->isvalidflag != ADDRESS_VALID %d\n", __func__, clientinfo->isvalidflag); if (size1 <= 0) dlt_vlog(LOG_ERR, "%s: size1 <= 0\n", __func__); if (size2 <= 0) dlt_vlog(LOG_ERR, "%s: size2 <= 0\n", __func__); } }