XCP_SIM
wineth.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 <memory.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 
31 #include "xcp.h"
32 #include "xcp_eth.h"
33 #include "xcp_hw.h"
36 #define DEFAULT_FAMILY PF_UNSPEC // Accept either IPv4 or IPv6
37 #define DEFAULT_SOCKTYPE SOCK_STREAM //
38 
39 #define ADDR_LEN sizeof(SOCKADDR_STORAGE)
40 
41 extern XcpTl_ConnectionType XcpTl_Connection;
42 
43 void Xcp_DispatchCommand(Xcp_PduType const *const pdu);
44 
45 extern Xcp_PduType Xcp_CtoIn;
46 extern Xcp_PduType Xcp_CtoOut;
47 
48 static boolean Xcp_EnableSocketOption(SOCKET sock, int option);
49 
50 #if 0
51 static boolean Xcp_DisableSocketOption(SOCKET sock, int option);
52 #endif
53 
54 static boolean Xcp_EnableSocketOption(SOCKET sock, int option) {
55 #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
56  const char enable = 1;
57 
58  if (setsockopt(sock, SOL_SOCKET, option, &enable, sizeof(int)) < 0) {
59  return XCP_FALSE;
60  }
61 #else
62  if (setsockopt(sock, SOL_SOCKET, option, &(const char){1}, sizeof(int)) < 0) {
63  return XCP_FALSE;
64  }
65 #endif
66  return XCP_TRUE;
67 }
68 
69 #if 0
70 static boolean Xcp_DisableSocketOption(SOCKET sock, int option)
71 {
72 #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
73  const char enable = 0;
74 
75  if (setsockopt(sock, SOL_SOCKET, option, &enable, sizeof(int)) < 0) {
76  return XCP_FALSE;
77  }
78 #else
79  if (setsockopt(sock, SOL_SOCKET, option, &(const char){0}, sizeof(int)) < 0) {
80  return XCP_FALSE;
81  }
82 #endif
83  return XCP_TRUE;
84 }
85 #endif
86 
87 void XcpTl_Init(void) {
88  WSADATA wsa;
89  ADDRINFO Hints;
90  ADDRINFO *AddrInfo;
91  ADDRINFO *AI;
92  char *Address = NULL;
93  char *Port = "5555";
94  SOCKET serverSockets[FD_SETSIZE];
95  int boundSocketNum = -1;
96  int ret;
97  int idx;
98  DWORD dwTimeAdjustment = 0UL;
99  DWORD dwTimeIncrement = 0UL;
100  BOOL fAdjustmentDisabled = XCP_TRUE;
101  /* unsigned long ul = 1; */
102 
103  ZeroMemory(&XcpTl_Connection, sizeof(XcpTl_ConnectionType));
104  memset(&Hints, 0, sizeof(Hints));
105  GetSystemTimeAdjustment(&dwTimeAdjustment, &dwTimeIncrement,
106  &fAdjustmentDisabled);
107  if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
108  XcpHw_ErrorMsg("XcpTl_Init:WSAStartup()", WSAGetLastError());
109  exit(EXIT_FAILURE);
110  } else {
111  }
112  XcpTl_Connection.socketType = Xcp_Options.tcp ? SOCK_STREAM : SOCK_DGRAM;
113  Hints.ai_family = Xcp_Options.ipv6 ? PF_INET6 : PF_INET;
114  Hints.ai_socktype = XcpTl_Connection.socketType;
115  Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
116  ret = getaddrinfo(Address, Port, &Hints, &AddrInfo);
117  if (ret != 0) {
118  XcpHw_ErrorMsg("XcpTl_Init::getaddrinfo()", WSAGetLastError());
119  WSACleanup();
120  return;
121  }
122  for (idx = 0, AI = AddrInfo; AI != NULL; AI = AI->ai_next, ++idx) {
123  if (idx == FD_SETSIZE) {
124  printf("getaddrinfo returned more addresses than we could use.\n");
125  break;
126  }
127  if ((AI->ai_family != PF_INET) && (AI->ai_family != PF_INET6)) {
128  continue;
129  }
130  serverSockets[idx] =
131  socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);
132  if (serverSockets[idx] == INVALID_SOCKET) {
133  XcpHw_ErrorMsg("XcpTl_Init::socket()", WSAGetLastError());
134  continue;
135  }
136  if (bind(serverSockets[idx], AI->ai_addr, AI->ai_addrlen) != 0) {
137  XcpHw_ErrorMsg("XcpTl_Init::bind()", WSAGetLastError());
138  continue;
139  }
140 
141  memcpy(&XcpTl_Connection.localAddress, AI->ai_addr,
142  sizeof(SOCKADDR_STORAGE));
143  // XcpTl_Connection.localAddress = *AI->ai_addr;
144 
145  if (XcpTl_Connection.socketType == SOCK_STREAM) {
146  if (listen(serverSockets[idx], 1) == SOCKET_ERROR) {
147  XcpHw_ErrorMsg("XcpTl_Init::listen()", WSAGetLastError());
148  continue;
149  }
150  }
151  boundSocketNum = idx;
152  XcpTl_Connection.boundSocket = serverSockets[boundSocketNum];
153  /* ioctlsocket(XcpTl_Connection.boundSocket, FIONBIO, &ul); */
154  break; /* Grab first address. */
155  }
156  freeaddrinfo(AddrInfo);
157  if (boundSocketNum == -1) {
158  fprintf(stderr,
159  "Fatal error: unable to serve on any address.\nPerhaps"
160  " a server is already running on port %u / %s [%s]?\n",
161  XCP_ETH_DEFAULT_PORT, Xcp_Options.tcp ? "TCP" : "UDP",
162  Xcp_Options.ipv6 ? "IPv6" : "IPv4");
163  WSACleanup();
164  exit(2);
165  }
166  if (!Xcp_EnableSocketOption(XcpTl_Connection.boundSocket, SO_REUSEADDR)) {
167  XcpHw_ErrorMsg("XcpTl_Init:setsockopt(SO_REUSEADDR)", WSAGetLastError());
168  }
169 #if 0
170  mode = 1;
171  ioctlsocket(XcpTl_Connection.boundSocket, FIONBIO, &ul);
172 #endif
173 }
174 
175 void XcpTl_DeInit(void) {
176  closesocket(XcpTl_Connection.boundSocket);
177  WSACleanup();
178 }
179 
180 void XcpTl_Send(uint8_t const *buf, uint16_t len) {
181  XCP_TL_ENTER_CRITICAL();
182  if (XcpTl_Connection.socketType == SOCK_DGRAM) {
183  if (sendto(XcpTl_Connection.boundSocket, (char const *)buf, len, 0,
184  (SOCKADDR const *)(SOCKADDR_STORAGE const *)&XcpTl_Connection
185  .connectionAddress,
186  ADDR_LEN) == SOCKET_ERROR) {
187  XcpHw_ErrorMsg("XcpTl_Send:sendto()", WSAGetLastError());
188  }
189  } else if (XcpTl_Connection.socketType == SOCK_STREAM) {
190  if (send(XcpTl_Connection.connectedSocket, (char const *)buf, len, 0) ==
191  SOCKET_ERROR) {
192  XcpHw_ErrorMsg("XcpTl_Send:send()", WSAGetLastError());
193  closesocket(XcpTl_Connection.connectedSocket);
194  }
195  }
196  XCP_TL_LEAVE_CRITICAL();
197 }