Goto sanos source index
//
// wsock32.c
//
// Windows Socket Library
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
//#define TRACEAPI
#include <os.h>
#include <sys/types.h>
#include <win32.h>
#include <string.h>
#include <inifile.h>
//#define sockapi __declspec(dllexport)
#define sockapi
#define SIO_GET_INTERFACE_LIST _IOCR('t', 127, unsigned long)
#define WSADESCRIPTION_LEN 256
#define WSASYS_STATUS_LEN 128
#define WSAERRBASE 10000
typedef handle_t SOCKET;
typedef handle_t WSAEVENT;
typedef struct iovec WSABUF;
typedef struct iovec *LPWSABUF;
typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN + 1];
char szSystemStatus[WSASYS_STATUS_LEN + 1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char *lpVendorInfo;
} WSADATA, *LPWSADATA;
#define IFF_UP 0x00000001 // Interface is up
#define IFF_BROADCAST 0x00000002 // Broadcast is supported
#define IFF_LOOPBACK 0x00000004 // Loopback interface
#define IFF_POINTTOPOINT 0x00000008 // Point-to-point interface
#define IFF_MULTICAST 0x00000010 // Multicast is supported
typedef struct _INTERFACE_INFO {
unsigned long iiFlags; // Type and status of the interface
struct sockaddr iiAddress; // Interface address
char filler1[8];
struct sockaddr iiBroadcastAddress; // Broadcast address
char filler2[8];
struct sockaddr iiNetmask; // Network mask
char filler3[8];
} INTERFACE_INFO;
sockapi int __stdcall WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData) {
TRACE("WSAStartup");
if (lpWSAData) {
lpWSAData->wVersion = 0x0101;
lpWSAData->wHighVersion = 0x0101;
strcpy(lpWSAData->szDescription, "Sanos Winsock 1.1");
strcpy(lpWSAData->szSystemStatus, "Running");
lpWSAData->iMaxSockets = 0xFFFF;
lpWSAData->iMaxUdpDg = 1500 - 40 - 8;
lpWSAData->lpVendorInfo = NULL;
}
return 0;
}
sockapi int __stdcall winsock_recv(SOCKET s,char *buf, int len, int flags) {
TRACE("recv");
return recv(s, buf, len, flags);
}
sockapi int __stdcall winsock_send(SOCKET s, const char *buf, int len, int flags) {
TRACE("send");
return send(s, buf, len, flags);
}
sockapi int __stdcall winsock_listen(SOCKET s, int backlog) {
TRACE("listen");
return listen(s, backlog);
}
sockapi int __stdcall winsock_bind(SOCKET s, const struct sockaddr *name, int namelen) {
TRACE("bind");
return bind(s, name, namelen);
}
sockapi SOCKET __stdcall winsock_accept(SOCKET s, struct sockaddr *addr, int *addrlen) {
TRACE("accept");
return accept(s, addr, addrlen);
}
sockapi int __stdcall winsock_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen) {
TRACE("recvfrom");
return recvfrom(s, buf, len, flags, from, fromlen);
}
sockapi int __stdcall winsock_sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen) {
TRACE("sendto");
return sendto(s, buf, len, flags, to, tolen);
}
sockapi int __stdcall winsock_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout) {
int rc;
TRACE("select");
rc = select(nfds, readfds, writefds, exceptfds, timeout);
if (rc < 0) {
if (errno == ETIMEOUT) return 0;
return -1;
}
return rc;
}
sockapi int __stdcall winsock_connect(SOCKET s, const struct sockaddr *name, int namelen) {
TRACE("connect");
return connect(s, name, namelen);
}
sockapi int __stdcall winsock_closesocket(SOCKET s) {
TRACE("closesocket");
return close(s);
}
sockapi int __stdcall winsock_shutdown(SOCKET s, int how) {
TRACE("shutdown");
return shutdown(s, how);
}
sockapi int __stdcall winsock_gethostname(char *name, int namelen) {
TRACE("gethostname");
return gethostname(name, namelen);
}
sockapi struct hostent * __stdcall winsock_gethostbyaddr(const char *addr, int len, int type) {
TRACE("gethostbyaddr");
return gethostbyaddr(addr, len, type);
}
sockapi struct hostent * __stdcall winsock_gethostbyname(const char *name) {
TRACE("gethostbyname");
return gethostbyname(name);
}
sockapi unsigned short __stdcall winsock_htons(unsigned short hostshort) {
TRACE("htons");
return htons(hostshort);
}
sockapi unsigned long __stdcall winsock_htonl(unsigned long hostlong) {
TRACE("htonl");
return htonl(hostlong);
}
sockapi unsigned short __stdcall winsock_ntohs(unsigned short netshort) {
TRACE("ntohs");
return ntohs(netshort);
}
sockapi unsigned long __stdcall winsock_ntohl(unsigned long netlong) {
TRACE("ntohl");
return ntohl(netlong);
}
sockapi int __stdcall winsock_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen) {
TRACE("getsockopt");
return getsockopt(s, level, optname, optval, optlen);
}
sockapi int __stdcall winsock_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen) {
int rc;
TRACE("setsockopt");
if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
syslog(LOG_DEBUG, "setsockopt: SO_REUSEADDR ignored");
return 0;
}
rc = setsockopt(s, level, optname, optval, optlen);
if (rc < 0) {
syslog(LOG_DEBUG, "setsockopt level %d optname %d failed: %d", level, optname, rc);
return -1;
}
return rc;
}
sockapi struct protoent * __stdcall winsock_getprotobyname(const char *name) {
TRACE("getprotobyname");
return getprotobyname(name);
}
sockapi int __stdcall winsock_getsockname(SOCKET s, struct sockaddr *name, int *namelen) {
TRACE("getsockname");
return getsockname(s, name, namelen);
}
sockapi SOCKET __stdcall winsock_socket(int af, int type, int protocol) {
TRACE("socket");
return socket(af, type, protocol);
}
sockapi int __stdcall winsock_ioctlsocket(SOCKET s, long cmd, unsigned long *argp) {
TRACE("ioctlsocket");
return ioctl(s, cmd, argp, 4);
}
sockapi int __stdcall __WSAFDIsSet(SOCKET s, fd_set *fd) {
TRACE("__WSAFDIsSet");
return FD_ISSET(s, fd);
}
sockapi int __stdcall WSAGetLastError() {
int err = gettib()->errnum;
TRACE("WSAGetLastError");
if (err == 0) return 0;
if (err == EAGAIN) return EWOULDBLOCK + WSAERRBASE;
if (err == EBADF) return ENOTSOCK + WSAERRBASE;
if (err < 45) return err + WSAERRBASE;
if (err < 82) return (err - 10) + WSAERRBASE;
if (err == EHOSTNOTFOUND) return 1001 + WSAERRBASE;
if (err == ETRYAGAIN) return 1002 + WSAERRBASE;
if (err == ENORECOVERY) return 1003 + WSAERRBASE;
if (err == ENODATA) return 1004 + WSAERRBASE;
return EIO;
}
sockapi int __stdcall WSACleanup() {
TRACE("WSACleanup");
return 0;
}
sockapi int __stdcall WSARecvFrom(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRecvd,
LPDWORD lpFlags,
struct sockaddr *lpFrom,
LPINT lpFromlen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) {
struct msghdr msg;
int rc;
TRACE("WSARecvFrom");
if (lpOverlapped != NULL) panic("Overlapped I/O not implemented in WSARecvFrom");
if (lpCompletionRoutine != NULL) panic("Completion routines not implemented in WSARecvFrom");
msg.msg_iov = lpBuffers;
msg.msg_iovlen = dwBufferCount;
msg.msg_name = lpFrom;
msg.msg_namelen = lpFromlen ? *lpFromlen : 0;
rc = recvmsg(s, &msg, lpFlags ? *lpFlags : 0);
if (rc < 0) return -1;
if (lpFromlen) *lpFromlen = msg.msg_namelen;
if (lpNumberOfBytesRecvd) *lpNumberOfBytesRecvd = rc;
return 0;
}
sockapi int __stdcall WSASendTo(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
const struct sockaddr *lpTo,
int iToLen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) {
struct msghdr msg;
int rc;
TRACE("WSASendTo");
if (lpOverlapped != NULL) panic("Overlapped I/O not implemented in WSASendTo");
if (lpCompletionRoutine != NULL) panic("Completion routines not implemented in WSASendTo");
msg.msg_iov = lpBuffers;
msg.msg_iovlen = dwBufferCount;
msg.msg_name = (struct sockaddr *) lpTo;
msg.msg_namelen = iToLen;
rc = sendmsg(s, &msg, dwFlags);
if (rc < 0) return -1;
if (lpNumberOfBytesSent) *lpNumberOfBytesSent = rc;
return 0;
}
sockapi int __stdcall WSAIoctl(
SOCKET s,
DWORD dwIoControlCode,
LPVOID lpvInBuffer,
DWORD cbInBuffer,
LPVOID lpvOutBuffer,
DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) {
TRACE("WSAIoctl");
if (dwIoControlCode == SIO_GET_INTERFACE_LIST) {
int i;
INTERFACE_INFO *ifinfo = lpvOutBuffer;
int numifs = cbOutBuffer / sizeof(INTERFACE_INFO);
int bufsize = numifs * sizeof(struct ifcfg);
struct ifcfg *iflist = malloc(bufsize);
int rc = ioctl(s, SIOIFLIST, iflist, bufsize);
if (rc < 0) {
free(iflist);
return -1;
}
if (rc > bufsize) {
errno = ENOBUFS;
free(iflist);
return -1;
}
numifs = rc / sizeof(struct ifcfg);
memset(ifinfo, 0, numifs * sizeof(INTERFACE_INFO));
for (i = 0; i < numifs; i++) {
ifinfo[i].iiFlags = IFF_BROADCAST;
if (iflist[i].flags & IFCFG_UP) ifinfo[i].iiFlags |= IFF_UP;
if (iflist[i].flags & IFCFG_LOOPBACK) ifinfo[i].iiFlags |= IFF_LOOPBACK;
memcpy(&ifinfo[i].iiAddress, &iflist[i].addr, sizeof(struct sockaddr));
memcpy(&ifinfo[i].iiNetmask, &iflist[i].netmask, sizeof(struct sockaddr));
memcpy(&ifinfo[i].iiBroadcastAddress, &iflist[i].broadcast, sizeof(struct sockaddr));
}
if (lpcbBytesReturned) *lpcbBytesReturned = numifs * sizeof(INTERFACE_INFO);
free(iflist);
return 0;
} else {
panic("WSAIoctl not implemented");
}
return 0;
}
sockapi int __stdcall WSASendDisconnect(
SOCKET s,
LPWSABUF lpOutboundDisconnectData) {
TRACE("WSASendDisconnect");
syslog(LOG_WARNING, "WSASendDisconnect not implemented");
return -1;
}
sockapi int __stdcall WSAEventSelect(
SOCKET s,
WSAEVENT hEventObject,
long lNetworkEvents) {
TRACE("WSAEventSelect");
// Just ignore call if it is an unregistration
// Used by nio when setting a socket to blocking mode
if (hEventObject == 0 && lNetworkEvents == 0) return 0;
panic("WSAEventSelect not implemented");
return -1;
}
sockapi int __stdcall WSARecv(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRecvd,
LPDWORD lpFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) {
int rc;
TRACE("WSARecv");
if (lpOverlapped != NULL) panic("Overlapped I/O not implemented in WSARecv");
if (lpCompletionRoutine != NULL) panic("Completion routines not implemented in WSARecv");
rc = readv(s, lpBuffers, dwBufferCount);
if (rc < 0) return -1;
if (lpNumberOfBytesRecvd) *lpNumberOfBytesRecvd = rc;
return 0;
}
sockapi int __stdcall WSASend(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) {
int rc;
TRACE("WSASend");
if (lpOverlapped != NULL) panic("Overlapped I/O not implemented in WSASend");
if (lpCompletionRoutine != NULL) panic("Completion routines not implemented in WSASend");
rc = writev(s, lpBuffers, dwBufferCount);
if (rc < 0) return -1;
if (lpNumberOfBytesSent) *lpNumberOfBytesSent = rc;
return 0;
}
int __stdcall DllMain(handle_t hmod, int reason, void *reserved) {
return TRUE;
}