XCP_SIM
linuxeth.c
1 /*
2  * BlueParrot XCP
3  *
4  * (C) 2007-2021 by Christoph Schueler <github.com/Christoph2,
5  * cpu12.gems@googlemail.com>
6  *
7  * All Rights Reserved
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * s. FLOSS-EXCEPTION.txt
24  */
25 
26 #include <stdio.h>
27 
29 #include "xcp.h"
30 #include "xcp_eth.h"
31 #include "xcp_hw.h"
34 socklen_t addrSize = sizeof(struct sockaddr_storage);
35 
36 extern XcpTl_ConnectionType XcpTl_Connection;
37 
38 static bool Xcp_EnableSocketOption(int sock, int option);
39 static bool Xcp_DisableSocketOption(int sock, int option);
40 
41 static bool Xcp_EnableSocketOption(int sock, int option) {
42 #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
43  const char enable = 1;
44 
45  if (setsockopt(sock, SOL_SOCKET, option, &enable, sizeof(int)) < 0) {
46  return false;
47  }
48 #else
49  if (setsockopt(sock, SOL_SOCKET, option, &(const char){1}, sizeof(int)) < 0) {
50  return false;
51  }
52 #endif
53  return true;
54 }
55 
56 static bool Xcp_DisableSocketOption(int sock, int option) {
57 #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
58  const char enable = 0;
59 
60  if (setsockopt(sock, SOL_SOCKET, option, &enable, sizeof(int)) < 0) {
61  return false;
62  }
63 #else
64  if (setsockopt(sock, SOL_SOCKET, option, &(const char){0}, sizeof(int)) < 0) {
65  return false;
66  }
67 #endif
68  return true;
69 }
70 
71 void XcpTl_Init(void) {
72  struct addrinfo hints;
73  struct addrinfo *addr_info = NULL;
74  char *address = NULL;
75  char port[16];
76  int sock = 0;
77  int ret = 0;
78 
79  XcpUtl_ZeroMem(&XcpTl_Connection, sizeof(XcpTl_ConnectionType));
80  memset(&hints, 0, sizeof(hints));
81  XcpTl_Connection.socketType = Xcp_Options.tcp ? SOCK_STREAM : SOCK_DGRAM;
82  sprintf(port, "%d", Xcp_Options.port);
83  hints.ai_family = Xcp_Options.ipv6 ? PF_INET6 : PF_INET;
84  hints.ai_socktype = XcpTl_Connection.socketType;
85  hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
86  ret = getaddrinfo(address, port, &hints, &addr_info);
87 
88  if (ret != 0) {
89  XcpHw_ErrorMsg("XcpTl_Init::getaddrinfo()", errno);
90  return;
91  }
92 
93  sock = socket(addr_info->ai_family, addr_info->ai_socktype, addr_info->ai_protocol);
94  if (sock == -1) {
95  XcpHw_ErrorMsg("XcpTl_Init::socket()", errno);
96  return;
97  }
98  if (bind(sock, addr_info->ai_addr, addr_info->ai_addrlen) == -1) {
99  XcpHw_ErrorMsg("XcpTl_Init::bind()", errno);
100  return;
101  }
102  if (XcpTl_Connection.socketType == SOCK_STREAM) {
103  if (listen(sock, 1) == -1) {
104  XcpHw_ErrorMsg("XcpTl_Init::listen()", errno);
105  return;
106  }
107  }
108 
109  memcpy(&XcpTl_Connection.localAddress, &addr_info->ai_addr, sizeof(XcpTl_Connection.localAddress));
110 
111  XcpTl_Connection.boundSocket = sock;
112  freeaddrinfo(addr_info);
113  if (!Xcp_EnableSocketOption(XcpTl_Connection.boundSocket, SO_REUSEADDR)) {
114  XcpHw_ErrorMsg("XcpTl_Init:setsockopt(SO_REUSEADDR)", errno);
115  }
116 }
117 
118 void XcpTl_DeInit(void) { close(XcpTl_Connection.boundSocket); }
119 
120 void XcpTl_Send(uint8_t const *buf, uint16_t len) {
121  // XcpUtl_Hexdump(buf, len);
122  XCP_TL_ENTER_CRITICAL();
123  if (XcpTl_Connection.socketType == SOCK_DGRAM) {
124  if (sendto(XcpTl_Connection.boundSocket, (char const *)buf, len, 0,
125  (struct sockaddr const *)&XcpTl_Connection.connectionAddress, addrSize) == -1) {
126  XcpHw_ErrorMsg("XcpTl_Send:sendto()", errno);
127  }
128  } else if (XcpTl_Connection.socketType == SOCK_STREAM) {
129  if (send(XcpTl_Connection.connectedSocket, (char const *)buf, len, 0) == -1) {
130  XcpHw_ErrorMsg("XcpTl_Send:send()", errno);
131  close(XcpTl_Connection.connectedSocket);
132  }
133  }
134  XCP_TL_LEAVE_CRITICAL();
135 }