summaryrefslogtreecommitdiffstats
path: root/winpr/libwinpr/winsock
diff options
context:
space:
mode:
Diffstat (limited to 'winpr/libwinpr/winsock')
-rw-r--r--winpr/libwinpr/winsock/CMakeLists.txt22
-rw-r--r--winpr/libwinpr/winsock/ModuleOptions.cmake8
-rw-r--r--winpr/libwinpr/winsock/winsock.c1290
3 files changed, 1320 insertions, 0 deletions
diff --git a/winpr/libwinpr/winsock/CMakeLists.txt b/winpr/libwinpr/winsock/CMakeLists.txt
new file mode 100644
index 0000000..ef13cd1
--- /dev/null
+++ b/winpr/libwinpr/winsock/CMakeLists.txt
@@ -0,0 +1,22 @@
+# WinPR: Windows Portable Runtime
+# libwinpr-winsock cmake build script
+#
+# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+winpr_module_add(winsock.c)
+
+if(WIN32)
+ winpr_library_add_public(ws2_32)
+endif()
diff --git a/winpr/libwinpr/winsock/ModuleOptions.cmake b/winpr/libwinpr/winsock/ModuleOptions.cmake
new file mode 100644
index 0000000..af49b6e
--- /dev/null
+++ b/winpr/libwinpr/winsock/ModuleOptions.cmake
@@ -0,0 +1,8 @@
+
+set(MINWIN_LAYER "0")
+set(MINWIN_GROUP "none")
+set(MINWIN_MAJOR_VERSION "0")
+set(MINWIN_MINOR_VERSION "0")
+set(MINWIN_SHORT_NAME "winsock")
+set(MINWIN_LONG_NAME "Windows Sockets (Winsock)")
+set(MODULE_LIBRARY_NAME "${MINWIN_SHORT_NAME}")
diff --git a/winpr/libwinpr/winsock/winsock.c b/winpr/libwinpr/winsock/winsock.c
new file mode 100644
index 0000000..3ac8e50
--- /dev/null
+++ b/winpr/libwinpr/winsock/winsock.c
@@ -0,0 +1,1290 @@
+/**
+ * WinPR: Windows Portable Runtime
+ * Windows Sockets (Winsock)
+ *
+ * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <winpr/config.h>
+
+#include <winpr/crt.h>
+#include <winpr/synch.h>
+
+#include <winpr/winsock.h>
+
+#ifdef WINPR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef WINPR_HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+#ifdef WINPR_HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+
+#ifndef _WIN32
+#include <fcntl.h>
+#endif
+
+#ifdef __APPLE__
+#define WSAIOCTL_IFADDRS
+#include <ifaddrs.h>
+#endif
+
+/**
+ * ws2_32.dll:
+ *
+ * __WSAFDIsSet
+ * accept
+ * bind
+ * closesocket
+ * connect
+ * freeaddrinfo
+ * FreeAddrInfoEx
+ * FreeAddrInfoExW
+ * FreeAddrInfoW
+ * getaddrinfo
+ * GetAddrInfoExA
+ * GetAddrInfoExCancel
+ * GetAddrInfoExOverlappedResult
+ * GetAddrInfoExW
+ * GetAddrInfoW
+ * gethostbyaddr
+ * gethostbyname
+ * gethostname
+ * GetHostNameW
+ * getnameinfo
+ * GetNameInfoW
+ * getpeername
+ * getprotobyname
+ * getprotobynumber
+ * getservbyname
+ * getservbyport
+ * getsockname
+ * getsockopt
+ * htonl
+ * htons
+ * inet_addr
+ * inet_ntoa
+ * inet_ntop
+ * inet_pton
+ * InetNtopW
+ * InetPtonW
+ * ioctlsocket
+ * listen
+ * ntohl
+ * ntohs
+ * recv
+ * recvfrom
+ * select
+ * send
+ * sendto
+ * SetAddrInfoExA
+ * SetAddrInfoExW
+ * setsockopt
+ * shutdown
+ * socket
+ * WahCloseApcHelper
+ * WahCloseHandleHelper
+ * WahCloseNotificationHandleHelper
+ * WahCloseSocketHandle
+ * WahCloseThread
+ * WahCompleteRequest
+ * WahCreateHandleContextTable
+ * WahCreateNotificationHandle
+ * WahCreateSocketHandle
+ * WahDestroyHandleContextTable
+ * WahDisableNonIFSHandleSupport
+ * WahEnableNonIFSHandleSupport
+ * WahEnumerateHandleContexts
+ * WahInsertHandleContext
+ * WahNotifyAllProcesses
+ * WahOpenApcHelper
+ * WahOpenCurrentThread
+ * WahOpenHandleHelper
+ * WahOpenNotificationHandleHelper
+ * WahQueueUserApc
+ * WahReferenceContextByHandle
+ * WahRemoveHandleContext
+ * WahWaitForNotification
+ * WahWriteLSPEvent
+ * WEP
+ * WPUCompleteOverlappedRequest
+ * WPUGetProviderPathEx
+ * WSAAccept
+ * WSAAddressToStringA
+ * WSAAddressToStringW
+ * WSAAdvertiseProvider
+ * WSAAsyncGetHostByAddr
+ * WSAAsyncGetHostByName
+ * WSAAsyncGetProtoByName
+ * WSAAsyncGetProtoByNumber
+ * WSAAsyncGetServByName
+ * WSAAsyncGetServByPort
+ * WSAAsyncSelect
+ * WSACancelAsyncRequest
+ * WSACancelBlockingCall
+ * WSACleanup
+ * WSACloseEvent
+ * WSAConnect
+ * WSAConnectByList
+ * WSAConnectByNameA
+ * WSAConnectByNameW
+ * WSACreateEvent
+ * WSADuplicateSocketA
+ * WSADuplicateSocketW
+ * WSAEnumNameSpaceProvidersA
+ * WSAEnumNameSpaceProvidersExA
+ * WSAEnumNameSpaceProvidersExW
+ * WSAEnumNameSpaceProvidersW
+ * WSAEnumNetworkEvents
+ * WSAEnumProtocolsA
+ * WSAEnumProtocolsW
+ * WSAEventSelect
+ * WSAGetLastError
+ * WSAGetOverlappedResult
+ * WSAGetQOSByName
+ * WSAGetServiceClassInfoA
+ * WSAGetServiceClassInfoW
+ * WSAGetServiceClassNameByClassIdA
+ * WSAGetServiceClassNameByClassIdW
+ * WSAHtonl
+ * WSAHtons
+ * WSAInstallServiceClassA
+ * WSAInstallServiceClassW
+ * WSAIoctl
+ * WSAIsBlocking
+ * WSAJoinLeaf
+ * WSALookupServiceBeginA
+ * WSALookupServiceBeginW
+ * WSALookupServiceEnd
+ * WSALookupServiceNextA
+ * WSALookupServiceNextW
+ * WSANSPIoctl
+ * WSANtohl
+ * WSANtohs
+ * WSAPoll
+ * WSAProviderCompleteAsyncCall
+ * WSAProviderConfigChange
+ * WSApSetPostRoutine
+ * WSARecv
+ * WSARecvDisconnect
+ * WSARecvFrom
+ * WSARemoveServiceClass
+ * WSAResetEvent
+ * WSASend
+ * WSASendDisconnect
+ * WSASendMsg
+ * WSASendTo
+ * WSASetBlockingHook
+ * WSASetEvent
+ * WSASetLastError
+ * WSASetServiceA
+ * WSASetServiceW
+ * WSASocketA
+ * WSASocketW
+ * WSAStartup
+ * WSAStringToAddressA
+ * WSAStringToAddressW
+ * WSAUnadvertiseProvider
+ * WSAUnhookBlockingHook
+ * WSAWaitForMultipleEvents
+ * WSCDeinstallProvider
+ * WSCDeinstallProviderEx
+ * WSCEnableNSProvider
+ * WSCEnumProtocols
+ * WSCEnumProtocolsEx
+ * WSCGetApplicationCategory
+ * WSCGetApplicationCategoryEx
+ * WSCGetProviderInfo
+ * WSCGetProviderPath
+ * WSCInstallNameSpace
+ * WSCInstallNameSpaceEx
+ * WSCInstallNameSpaceEx2
+ * WSCInstallProvider
+ * WSCInstallProviderAndChains
+ * WSCInstallProviderEx
+ * WSCSetApplicationCategory
+ * WSCSetApplicationCategoryEx
+ * WSCSetProviderInfo
+ * WSCUnInstallNameSpace
+ * WSCUnInstallNameSpaceEx2
+ * WSCUpdateProvider
+ * WSCUpdateProviderEx
+ * WSCWriteNameSpaceOrder
+ * WSCWriteProviderOrder
+ * WSCWriteProviderOrderEx
+ */
+
+#ifdef _WIN32
+
+#if (_WIN32_WINNT < 0x0600)
+
+PCSTR winpr_inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize)
+{
+ if (Family == AF_INET)
+ {
+ struct sockaddr_in in = { 0 };
+
+ in.sin_family = AF_INET;
+ memcpy(&in.sin_addr, pAddr, sizeof(struct in_addr));
+ getnameinfo((struct sockaddr*)&in, sizeof(struct sockaddr_in), pStringBuf, StringBufSize,
+ NULL, 0, NI_NUMERICHOST);
+ return pStringBuf;
+ }
+ else if (Family == AF_INET6)
+ {
+ struct sockaddr_in6 in = { 0 };
+
+ in.sin6_family = AF_INET6;
+ memcpy(&in.sin6_addr, pAddr, sizeof(struct in_addr6));
+ getnameinfo((struct sockaddr*)&in, sizeof(struct sockaddr_in6), pStringBuf, StringBufSize,
+ NULL, 0, NI_NUMERICHOST);
+ return pStringBuf;
+ }
+
+ return NULL;
+}
+
+INT winpr_inet_pton(INT Family, PCSTR pszAddrString, PVOID pAddrBuf)
+{
+ SOCKADDR_STORAGE addr;
+ int addr_len = sizeof(addr);
+
+ if ((Family != AF_INET) && (Family != AF_INET6))
+ return -1;
+
+ if (WSAStringToAddressA((char*)pszAddrString, Family, NULL, (struct sockaddr*)&addr,
+ &addr_len) != 0)
+ return 0;
+
+ if (Family == AF_INET)
+ {
+ memcpy(pAddrBuf, &((struct sockaddr_in*)&addr)->sin_addr, sizeof(struct in_addr));
+ }
+ else if (Family == AF_INET6)
+ {
+ memcpy(pAddrBuf, &((struct sockaddr_in6*)&addr)->sin6_addr, sizeof(struct in6_addr));
+ }
+
+ return 1;
+}
+
+#endif /* (_WIN32_WINNT < 0x0600) */
+
+#else /* _WIN32 */
+
+#include <netdb.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <net/if.h>
+
+#include <winpr/assert.h>
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
+int WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)
+{
+ WINPR_ASSERT(lpWSAData);
+
+ ZeroMemory(lpWSAData, sizeof(WSADATA));
+ lpWSAData->wVersion = wVersionRequired;
+ lpWSAData->wHighVersion = MAKEWORD(2, 2);
+ return 0; /* success */
+}
+
+int WSACleanup(void)
+{
+ return 0; /* success */
+}
+
+void WSASetLastError(int iError)
+{
+ switch (iError)
+ {
+ /* Base error codes */
+ case WSAEINTR:
+ errno = EINTR;
+ break;
+
+ case WSAEBADF:
+ errno = EBADF;
+ break;
+
+ case WSAEACCES:
+ errno = EACCES;
+ break;
+
+ case WSAEFAULT:
+ errno = EFAULT;
+ break;
+
+ case WSAEINVAL:
+ errno = EINVAL;
+ break;
+
+ case WSAEMFILE:
+ errno = EMFILE;
+ break;
+
+ /* BSD sockets error codes */
+
+ case WSAEWOULDBLOCK:
+ errno = EWOULDBLOCK;
+ break;
+
+ case WSAEINPROGRESS:
+ errno = EINPROGRESS;
+ break;
+
+ case WSAEALREADY:
+ errno = EALREADY;
+ break;
+
+ case WSAENOTSOCK:
+ errno = ENOTSOCK;
+ break;
+
+ case WSAEDESTADDRREQ:
+ errno = EDESTADDRREQ;
+ break;
+
+ case WSAEMSGSIZE:
+ errno = EMSGSIZE;
+ break;
+
+ case WSAEPROTOTYPE:
+ errno = EPROTOTYPE;
+ break;
+
+ case WSAENOPROTOOPT:
+ errno = ENOPROTOOPT;
+ break;
+
+ case WSAEPROTONOSUPPORT:
+ errno = EPROTONOSUPPORT;
+ break;
+
+ case WSAESOCKTNOSUPPORT:
+ errno = ESOCKTNOSUPPORT;
+ break;
+
+ case WSAEOPNOTSUPP:
+ errno = EOPNOTSUPP;
+ break;
+
+ case WSAEPFNOSUPPORT:
+ errno = EPFNOSUPPORT;
+ break;
+
+ case WSAEAFNOSUPPORT:
+ errno = EAFNOSUPPORT;
+ break;
+
+ case WSAEADDRINUSE:
+ errno = EADDRINUSE;
+ break;
+
+ case WSAEADDRNOTAVAIL:
+ errno = EADDRNOTAVAIL;
+ break;
+
+ case WSAENETDOWN:
+ errno = ENETDOWN;
+ break;
+
+ case WSAENETUNREACH:
+ errno = ENETUNREACH;
+ break;
+
+ case WSAENETRESET:
+ errno = ENETRESET;
+ break;
+
+ case WSAECONNABORTED:
+ errno = ECONNABORTED;
+ break;
+
+ case WSAECONNRESET:
+ errno = ECONNRESET;
+ break;
+
+ case WSAENOBUFS:
+ errno = ENOBUFS;
+ break;
+
+ case WSAEISCONN:
+ errno = EISCONN;
+ break;
+
+ case WSAENOTCONN:
+ errno = ENOTCONN;
+ break;
+
+ case WSAESHUTDOWN:
+ errno = ESHUTDOWN;
+ break;
+
+ case WSAETOOMANYREFS:
+ errno = ETOOMANYREFS;
+ break;
+
+ case WSAETIMEDOUT:
+ errno = ETIMEDOUT;
+ break;
+
+ case WSAECONNREFUSED:
+ errno = ECONNREFUSED;
+ break;
+
+ case WSAELOOP:
+ errno = ELOOP;
+ break;
+
+ case WSAENAMETOOLONG:
+ errno = ENAMETOOLONG;
+ break;
+
+ case WSAEHOSTDOWN:
+ errno = EHOSTDOWN;
+ break;
+
+ case WSAEHOSTUNREACH:
+ errno = EHOSTUNREACH;
+ break;
+
+ case WSAENOTEMPTY:
+ errno = ENOTEMPTY;
+ break;
+#ifdef EPROCLIM
+
+ case WSAEPROCLIM:
+ errno = EPROCLIM;
+ break;
+#endif
+
+ case WSAEUSERS:
+ errno = EUSERS;
+ break;
+
+ case WSAEDQUOT:
+ errno = EDQUOT;
+ break;
+
+ case WSAESTALE:
+ errno = ESTALE;
+ break;
+
+ case WSAEREMOTE:
+ errno = EREMOTE;
+ break;
+ }
+}
+
+int WSAGetLastError(void)
+{
+ int iError = 0;
+
+ switch (errno)
+ {
+ /* Base error codes */
+ case EINTR:
+ iError = WSAEINTR;
+ break;
+
+ case EBADF:
+ iError = WSAEBADF;
+ break;
+
+ case EACCES:
+ iError = WSAEACCES;
+ break;
+
+ case EFAULT:
+ iError = WSAEFAULT;
+ break;
+
+ case EINVAL:
+ iError = WSAEINVAL;
+ break;
+
+ case EMFILE:
+ iError = WSAEMFILE;
+ break;
+
+ /* BSD sockets error codes */
+
+ case EWOULDBLOCK:
+ iError = WSAEWOULDBLOCK;
+ break;
+
+ case EINPROGRESS:
+ iError = WSAEINPROGRESS;
+ break;
+
+ case EALREADY:
+ iError = WSAEALREADY;
+ break;
+
+ case ENOTSOCK:
+ iError = WSAENOTSOCK;
+ break;
+
+ case EDESTADDRREQ:
+ iError = WSAEDESTADDRREQ;
+ break;
+
+ case EMSGSIZE:
+ iError = WSAEMSGSIZE;
+ break;
+
+ case EPROTOTYPE:
+ iError = WSAEPROTOTYPE;
+ break;
+
+ case ENOPROTOOPT:
+ iError = WSAENOPROTOOPT;
+ break;
+
+ case EPROTONOSUPPORT:
+ iError = WSAEPROTONOSUPPORT;
+ break;
+
+ case ESOCKTNOSUPPORT:
+ iError = WSAESOCKTNOSUPPORT;
+ break;
+
+ case EOPNOTSUPP:
+ iError = WSAEOPNOTSUPP;
+ break;
+
+ case EPFNOSUPPORT:
+ iError = WSAEPFNOSUPPORT;
+ break;
+
+ case EAFNOSUPPORT:
+ iError = WSAEAFNOSUPPORT;
+ break;
+
+ case EADDRINUSE:
+ iError = WSAEADDRINUSE;
+ break;
+
+ case EADDRNOTAVAIL:
+ iError = WSAEADDRNOTAVAIL;
+ break;
+
+ case ENETDOWN:
+ iError = WSAENETDOWN;
+ break;
+
+ case ENETUNREACH:
+ iError = WSAENETUNREACH;
+ break;
+
+ case ENETRESET:
+ iError = WSAENETRESET;
+ break;
+
+ case ECONNABORTED:
+ iError = WSAECONNABORTED;
+ break;
+
+ case ECONNRESET:
+ iError = WSAECONNRESET;
+ break;
+
+ case ENOBUFS:
+ iError = WSAENOBUFS;
+ break;
+
+ case EISCONN:
+ iError = WSAEISCONN;
+ break;
+
+ case ENOTCONN:
+ iError = WSAENOTCONN;
+ break;
+
+ case ESHUTDOWN:
+ iError = WSAESHUTDOWN;
+ break;
+
+ case ETOOMANYREFS:
+ iError = WSAETOOMANYREFS;
+ break;
+
+ case ETIMEDOUT:
+ iError = WSAETIMEDOUT;
+ break;
+
+ case ECONNREFUSED:
+ iError = WSAECONNREFUSED;
+ break;
+
+ case ELOOP:
+ iError = WSAELOOP;
+ break;
+
+ case ENAMETOOLONG:
+ iError = WSAENAMETOOLONG;
+ break;
+
+ case EHOSTDOWN:
+ iError = WSAEHOSTDOWN;
+ break;
+
+ case EHOSTUNREACH:
+ iError = WSAEHOSTUNREACH;
+ break;
+
+ case ENOTEMPTY:
+ iError = WSAENOTEMPTY;
+ break;
+#ifdef EPROCLIM
+
+ case EPROCLIM:
+ iError = WSAEPROCLIM;
+ break;
+#endif
+
+ case EUSERS:
+ iError = WSAEUSERS;
+ break;
+
+ case EDQUOT:
+ iError = WSAEDQUOT;
+ break;
+
+ case ESTALE:
+ iError = WSAESTALE;
+ break;
+
+ case EREMOTE:
+ iError = WSAEREMOTE;
+ break;
+ /* Special cases */
+#if (EAGAIN != EWOULDBLOCK)
+
+ case EAGAIN:
+ iError = WSAEWOULDBLOCK;
+ break;
+#endif
+#if defined(EPROTO)
+
+ case EPROTO:
+ iError = WSAECONNRESET;
+ break;
+#endif
+ }
+
+ /**
+ * Windows Sockets Extended Error Codes:
+ *
+ * WSASYSNOTREADY
+ * WSAVERNOTSUPPORTED
+ * WSANOTINITIALISED
+ * WSAEDISCON
+ * WSAENOMORE
+ * WSAECANCELLED
+ * WSAEINVALIDPROCTABLE
+ * WSAEINVALIDPROVIDER
+ * WSAEPROVIDERFAILEDINIT
+ * WSASYSCALLFAILURE
+ * WSASERVICE_NOT_FOUND
+ * WSATYPE_NOT_FOUND
+ * WSA_E_NO_MORE
+ * WSA_E_CANCELLED
+ * WSAEREFUSED
+ */
+ return iError;
+}
+
+HANDLE WSACreateEvent(void)
+{
+ return CreateEvent(NULL, TRUE, FALSE, NULL);
+}
+
+BOOL WSASetEvent(HANDLE hEvent)
+{
+ return SetEvent(hEvent);
+}
+
+BOOL WSAResetEvent(HANDLE hEvent)
+{
+ /* POSIX systems auto reset the socket,
+ * if no more data is available. */
+ return TRUE;
+}
+
+BOOL WSACloseEvent(HANDLE hEvent)
+{
+ BOOL status = 0;
+ status = CloseHandle(hEvent);
+
+ if (!status)
+ SetLastError(6);
+
+ return status;
+}
+
+int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, LONG lNetworkEvents)
+{
+ u_long arg = 1;
+ ULONG mode = 0;
+
+ if (_ioctlsocket(s, FIONBIO, &arg) != 0)
+ return SOCKET_ERROR;
+
+ if (arg == 0)
+ return 0;
+
+ if (lNetworkEvents & FD_READ)
+ mode |= WINPR_FD_READ;
+
+ if (lNetworkEvents & FD_WRITE)
+ mode |= WINPR_FD_WRITE;
+
+ if (SetEventFileDescriptor(hEventObject, s, mode) < 0)
+ return SOCKET_ERROR;
+
+ return 0;
+}
+
+DWORD WSAWaitForMultipleEvents(DWORD cEvents, const HANDLE* lphEvents, BOOL fWaitAll,
+ DWORD dwTimeout, BOOL fAlertable)
+{
+ return WaitForMultipleObjectsEx(cEvents, lphEvents, fWaitAll, dwTimeout, fAlertable);
+}
+
+SOCKET WSASocketA(int af, int type, int protocol, LPWSAPROTOCOL_INFOA lpProtocolInfo, GROUP g,
+ DWORD dwFlags)
+{
+ SOCKET s = 0;
+ s = _socket(af, type, protocol);
+ return s;
+}
+
+SOCKET WSASocketW(int af, int type, int protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, GROUP g,
+ DWORD dwFlags)
+{
+ return WSASocketA(af, type, protocol, (LPWSAPROTOCOL_INFOA)lpProtocolInfo, g, dwFlags);
+}
+
+int WSAIoctl(SOCKET s, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
+ LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned,
+ LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+ int fd = 0;
+ int index = 0;
+ ULONG nFlags = 0;
+ size_t offset = 0;
+ size_t ifreq_len = 0;
+ struct ifreq* ifreq = NULL;
+ struct ifconf ifconf;
+ char address[128];
+ char broadcast[128];
+ char netmask[128];
+ char buffer[4096];
+ int numInterfaces = 0;
+ int maxNumInterfaces = 0;
+ INTERFACE_INFO* pInterface = NULL;
+ INTERFACE_INFO* pInterfaces = NULL;
+ struct sockaddr_in* pAddress = NULL;
+ struct sockaddr_in* pBroadcast = NULL;
+ struct sockaddr_in* pNetmask = NULL;
+
+ if ((dwIoControlCode != SIO_GET_INTERFACE_LIST) ||
+ (!lpvOutBuffer || !cbOutBuffer || !lpcbBytesReturned))
+ {
+ WSASetLastError(WSAEINVAL);
+ return SOCKET_ERROR;
+ }
+
+ fd = (int)s;
+ pInterfaces = (INTERFACE_INFO*)lpvOutBuffer;
+ maxNumInterfaces = cbOutBuffer / sizeof(INTERFACE_INFO);
+#ifdef WSAIOCTL_IFADDRS
+ {
+ struct ifaddrs* ifap = NULL;
+
+ if (getifaddrs(&ifap) != 0)
+ {
+ WSASetLastError(WSAENETDOWN);
+ return SOCKET_ERROR;
+ }
+
+ index = 0;
+ numInterfaces = 0;
+
+ for (struct ifaddrs* ifa = ifap; ifa; ifa = ifa->ifa_next)
+ {
+ pInterface = &pInterfaces[index];
+ pAddress = (struct sockaddr_in*)&pInterface->iiAddress;
+ pBroadcast = (struct sockaddr_in*)&pInterface->iiBroadcastAddress;
+ pNetmask = (struct sockaddr_in*)&pInterface->iiNetmask;
+ nFlags = 0;
+
+ if (ifa->ifa_flags & IFF_UP)
+ nFlags |= _IFF_UP;
+
+ if (ifa->ifa_flags & IFF_BROADCAST)
+ nFlags |= _IFF_BROADCAST;
+
+ if (ifa->ifa_flags & IFF_LOOPBACK)
+ nFlags |= _IFF_LOOPBACK;
+
+ if (ifa->ifa_flags & IFF_POINTOPOINT)
+ nFlags |= _IFF_POINTTOPOINT;
+
+ if (ifa->ifa_flags & IFF_MULTICAST)
+ nFlags |= _IFF_MULTICAST;
+
+ pInterface->iiFlags = nFlags;
+
+ if (ifa->ifa_addr)
+ {
+ if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6))
+ continue;
+
+ getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr), address, sizeof(address), 0, 0,
+ NI_NUMERICHOST);
+ inet_pton(ifa->ifa_addr->sa_family, address, (void*)&pAddress->sin_addr);
+ }
+ else
+ {
+ ZeroMemory(pAddress, sizeof(struct sockaddr_in));
+ }
+
+ if (ifa->ifa_dstaddr)
+ {
+ if ((ifa->ifa_dstaddr->sa_family != AF_INET) &&
+ (ifa->ifa_dstaddr->sa_family != AF_INET6))
+ continue;
+
+ getnameinfo(ifa->ifa_dstaddr, sizeof(struct sockaddr), broadcast, sizeof(broadcast),
+ 0, 0, NI_NUMERICHOST);
+ inet_pton(ifa->ifa_dstaddr->sa_family, broadcast, (void*)&pBroadcast->sin_addr);
+ }
+ else
+ {
+ ZeroMemory(pBroadcast, sizeof(struct sockaddr_in));
+ }
+
+ if (ifa->ifa_netmask)
+ {
+ if ((ifa->ifa_netmask->sa_family != AF_INET) &&
+ (ifa->ifa_netmask->sa_family != AF_INET6))
+ continue;
+
+ getnameinfo(ifa->ifa_netmask, sizeof(struct sockaddr), netmask, sizeof(netmask), 0,
+ 0, NI_NUMERICHOST);
+ inet_pton(ifa->ifa_netmask->sa_family, netmask, (void*)&pNetmask->sin_addr);
+ }
+ else
+ {
+ ZeroMemory(pNetmask, sizeof(struct sockaddr_in));
+ }
+
+ numInterfaces++;
+ index++;
+ }
+
+ *lpcbBytesReturned = (DWORD)(numInterfaces * sizeof(INTERFACE_INFO));
+ freeifaddrs(ifap);
+ return 0;
+ }
+#endif
+ ifconf.ifc_len = sizeof(buffer);
+ ifconf.ifc_buf = buffer;
+
+ if (ioctl(fd, SIOCGIFCONF, &ifconf) != 0)
+ {
+ WSASetLastError(WSAENETDOWN);
+ return SOCKET_ERROR;
+ }
+
+ index = 0;
+ offset = 0;
+ numInterfaces = 0;
+ ifreq = ifconf.ifc_req;
+
+ while ((ifconf.ifc_len >= 0) && (offset < (size_t)ifconf.ifc_len) &&
+ (numInterfaces < maxNumInterfaces))
+ {
+ pInterface = &pInterfaces[index];
+ pAddress = (struct sockaddr_in*)&pInterface->iiAddress;
+ pBroadcast = (struct sockaddr_in*)&pInterface->iiBroadcastAddress;
+ pNetmask = (struct sockaddr_in*)&pInterface->iiNetmask;
+
+ if (ioctl(fd, SIOCGIFFLAGS, ifreq) != 0)
+ goto next_ifreq;
+
+ nFlags = 0;
+
+ if (ifreq->ifr_flags & IFF_UP)
+ nFlags |= _IFF_UP;
+
+ if (ifreq->ifr_flags & IFF_BROADCAST)
+ nFlags |= _IFF_BROADCAST;
+
+ if (ifreq->ifr_flags & IFF_LOOPBACK)
+ nFlags |= _IFF_LOOPBACK;
+
+ if (ifreq->ifr_flags & IFF_POINTOPOINT)
+ nFlags |= _IFF_POINTTOPOINT;
+
+ if (ifreq->ifr_flags & IFF_MULTICAST)
+ nFlags |= _IFF_MULTICAST;
+
+ pInterface->iiFlags = nFlags;
+
+ if (ioctl(fd, SIOCGIFADDR, ifreq) != 0)
+ goto next_ifreq;
+
+ if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
+ goto next_ifreq;
+
+ getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr), address, sizeof(address), 0, 0,
+ NI_NUMERICHOST);
+ inet_pton(ifreq->ifr_addr.sa_family, address, (void*)&pAddress->sin_addr);
+
+ if (ioctl(fd, SIOCGIFBRDADDR, ifreq) != 0)
+ goto next_ifreq;
+
+ if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
+ goto next_ifreq;
+
+ getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr), broadcast, sizeof(broadcast), 0, 0,
+ NI_NUMERICHOST);
+ inet_pton(ifreq->ifr_addr.sa_family, broadcast, (void*)&pBroadcast->sin_addr);
+
+ if (ioctl(fd, SIOCGIFNETMASK, ifreq) != 0)
+ goto next_ifreq;
+
+ if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
+ goto next_ifreq;
+
+ getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr), netmask, sizeof(netmask), 0, 0,
+ NI_NUMERICHOST);
+ inet_pton(ifreq->ifr_addr.sa_family, netmask, (void*)&pNetmask->sin_addr);
+ numInterfaces++;
+ next_ifreq:
+#if !defined(__linux__) && !defined(__sun__) && !defined(__CYGWIN__) && !defined(EMSCRIPTEN)
+ ifreq_len = IFNAMSIZ + ifreq->ifr_addr.sa_len;
+#else
+ ifreq_len = sizeof(*ifreq);
+#endif
+ ifreq = (struct ifreq*)&((BYTE*)ifreq)[ifreq_len];
+ offset += ifreq_len;
+ index++;
+ }
+
+ *lpcbBytesReturned = (DWORD)(numInterfaces * sizeof(INTERFACE_INFO));
+ return 0;
+}
+
+SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen)
+{
+ int status = 0;
+ int fd = (int)s;
+ socklen_t s_addrlen = (socklen_t)*addrlen;
+ status = accept(fd, addr, &s_addrlen);
+ *addrlen = (socklen_t)s_addrlen;
+ return status;
+}
+
+int _bind(SOCKET s, const struct sockaddr* addr, int namelen)
+{
+ int status = 0;
+ int fd = (int)s;
+ status = bind(fd, addr, (socklen_t)namelen);
+
+ if (status < 0)
+ return SOCKET_ERROR;
+
+ return status;
+}
+
+int closesocket(SOCKET s)
+{
+ int status = 0;
+ int fd = (int)s;
+ status = close(fd);
+ return status;
+}
+
+int _connect(SOCKET s, const struct sockaddr* name, int namelen)
+{
+ int status = 0;
+ int fd = (int)s;
+ status = connect(fd, name, (socklen_t)namelen);
+
+ if (status < 0)
+ return SOCKET_ERROR;
+
+ return status;
+}
+
+int _ioctlsocket(SOCKET s, long cmd, u_long* argp)
+{
+ int fd = (int)s;
+
+ if (cmd == FIONBIO)
+ {
+ int flags = 0;
+
+ if (!argp)
+ return SOCKET_ERROR;
+
+ flags = fcntl(fd, F_GETFL);
+
+ if (flags == -1)
+ return SOCKET_ERROR;
+
+ if (*argp)
+ fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ else
+ fcntl(fd, F_SETFL, flags & ~(O_NONBLOCK));
+ }
+
+ return 0;
+}
+
+int _getpeername(SOCKET s, struct sockaddr* name, int* namelen)
+{
+ int status = 0;
+ int fd = (int)s;
+ socklen_t s_namelen = (socklen_t)*namelen;
+ status = getpeername(fd, name, &s_namelen);
+ *namelen = (int)s_namelen;
+ return status;
+}
+
+int _getsockname(SOCKET s, struct sockaddr* name, int* namelen)
+{
+ int status = 0;
+ int fd = (int)s;
+ socklen_t s_namelen = (socklen_t)*namelen;
+ status = getsockname(fd, name, &s_namelen);
+ *namelen = (int)s_namelen;
+ return status;
+}
+
+int _getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen)
+{
+ int status = 0;
+ int fd = (int)s;
+ socklen_t s_optlen = (socklen_t)*optlen;
+ status = getsockopt(fd, level, optname, (void*)optval, &s_optlen);
+ *optlen = (socklen_t)s_optlen;
+ return status;
+}
+
+u_long _htonl(u_long hostlong)
+{
+ return htonl(hostlong);
+}
+
+u_short _htons(u_short hostshort)
+{
+ return htons(hostshort);
+}
+
+unsigned long _inet_addr(const char* cp)
+{
+ return (long)inet_addr(cp);
+}
+
+char* _inet_ntoa(struct in_addr in)
+{
+ return inet_ntoa(in);
+}
+
+int _listen(SOCKET s, int backlog)
+{
+ int status = 0;
+ int fd = (int)s;
+ status = listen(fd, backlog);
+ return status;
+}
+
+u_long _ntohl(u_long netlong)
+{
+ return ntohl(netlong);
+}
+
+u_short _ntohs(u_short netshort)
+{
+ return ntohs(netshort);
+}
+
+int _recv(SOCKET s, char* buf, int len, int flags)
+{
+ int status = 0;
+ int fd = (int)s;
+ status = (int)recv(fd, (void*)buf, (size_t)len, flags);
+ return status;
+}
+
+int _recvfrom(SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen)
+{
+ int status = 0;
+ int fd = (int)s;
+ socklen_t s_fromlen = (socklen_t)*fromlen;
+ status = (int)recvfrom(fd, (void*)buf, (size_t)len, flags, from, &s_fromlen);
+ *fromlen = (int)s_fromlen;
+ return status;
+}
+
+int _select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds,
+ const struct timeval* timeout)
+{
+ int status = 0;
+ union
+ {
+ const struct timeval* cpv;
+ struct timeval* pv;
+ } cnv;
+ cnv.cpv = timeout;
+ do
+ {
+ status = select(nfds, readfds, writefds, exceptfds, cnv.pv);
+ } while ((status < 0) && (errno == EINTR));
+
+ return status;
+}
+
+int _send(SOCKET s, const char* buf, int len, int flags)
+{
+ int status = 0;
+ int fd = (int)s;
+ flags |= MSG_NOSIGNAL;
+ status = (int)send(fd, (const void*)buf, (size_t)len, flags);
+ return status;
+}
+
+int _sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen)
+{
+ int status = 0;
+ int fd = (int)s;
+ status = (int)sendto(fd, (const void*)buf, (size_t)len, flags, to, (socklen_t)tolen);
+ return status;
+}
+
+int _setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen)
+{
+ int status = 0;
+ int fd = (int)s;
+ status = setsockopt(fd, level, optname, (const void*)optval, (socklen_t)optlen);
+ return status;
+}
+
+int _shutdown(SOCKET s, int how)
+{
+ int status = 0;
+ int fd = (int)s;
+ int s_how = -1;
+
+ switch (how)
+ {
+ case SD_RECEIVE:
+ s_how = SHUT_RD;
+ break;
+
+ case SD_SEND:
+ s_how = SHUT_WR;
+ break;
+
+ case SD_BOTH:
+ s_how = SHUT_RDWR;
+ break;
+ }
+
+ if (s_how < 0)
+ return SOCKET_ERROR;
+
+ status = shutdown(fd, s_how);
+ return status;
+}
+
+SOCKET _socket(int af, int type, int protocol)
+{
+ int fd = 0;
+ SOCKET s = 0;
+ fd = socket(af, type, protocol);
+
+ if (fd < 0)
+ return INVALID_SOCKET;
+
+ s = (SOCKET)fd;
+ return s;
+}
+
+struct hostent* _gethostbyaddr(const char* addr, int len, int type)
+{
+ struct hostent* host = NULL;
+ host = gethostbyaddr((const void*)addr, (socklen_t)len, type);
+ return host;
+}
+
+struct hostent* _gethostbyname(const char* name)
+{
+ struct hostent* host = NULL;
+ host = gethostbyname(name);
+ return host;
+}
+
+int _gethostname(char* name, int namelen)
+{
+ int status = 0;
+ status = gethostname(name, (size_t)namelen);
+ return status;
+}
+
+struct servent* _getservbyport(int port, const char* proto)
+{
+ struct servent* serv = NULL;
+ serv = getservbyport(port, proto);
+ return serv;
+}
+
+struct servent* _getservbyname(const char* name, const char* proto)
+{
+ struct servent* serv = NULL;
+ serv = getservbyname(name, proto);
+ return serv;
+}
+
+struct protoent* _getprotobynumber(int number)
+{
+ struct protoent* proto = NULL;
+ proto = getprotobynumber(number);
+ return proto;
+}
+
+struct protoent* _getprotobyname(const char* name)
+{
+ struct protoent* proto = NULL;
+ proto = getprotobyname(name);
+ return proto;
+}
+
+#endif /* _WIN32 */