ClamAV is an open source (GPLv2) anti-virus toolkit.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
clamav/win32/compat/net.c

437 lines
11 KiB

/*
* Copyright (C) 2009 Sourcefire, Inc.
*
* Authors: aCaB <acab@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <winsock2.h>
#include <Ws2tcpip.h>
/* #define W2K_DNSAAPI_COMPAT */
#ifdef W2K_DNSAAPI_COMPAT
#include <Wspiapi.h>
#endif
#include <stdlib.h>
#include "net.h"
#include "w32_errno.h"
static void wsock2errno() {
switch(WSAGetLastError()) {
case WSA_INVALID_HANDLE:
case WSA_INVALID_PARAMETER:
case WSAVERNOTSUPPORTED:
case WSANOTINITIALISED:
case WSAEINVALIDPROCTABLE:
case WSAEINVALIDPROVIDER:
case WSAEPROVIDERFAILEDINIT:
case WSASYSCALLFAILURE:
case WSASERVICE_NOT_FOUND:
case WSATYPE_NOT_FOUND:
errno = EINVAL;
break;
case WSA_OPERATION_ABORTED:
case WSAENOMORE:
case WSAECANCELLED:
case WSA_E_NO_MORE:
case WSA_E_CANCELLED:
case WSA_IO_INCOMPLETE:
case WSA_IO_PENDING:
case WSAEREFUSED:
case WSA_QOS_RECEIVERS:
case WSA_QOS_SENDERS:
case WSA_QOS_NO_SENDERS:
case WSA_QOS_NO_RECEIVERS:
case WSA_QOS_REQUEST_CONFIRMED:
case WSA_QOS_ADMISSION_FAILURE:
case WSA_QOS_POLICY_FAILURE:
case WSA_QOS_BAD_STYLE:
case WSA_QOS_BAD_OBJECT:
case WSA_QOS_TRAFFIC_CTRL_ERROR:
case WSA_QOS_GENERIC_ERROR:
case WSA_QOS_ESERVICETYPE:
case WSA_QOS_EFLOWSPEC:
case WSA_QOS_EPROVSPECBUF:
case WSA_QOS_EFILTERSTYLE:
case WSA_QOS_EFILTERTYPE:
case WSA_QOS_EFILTERCOUNT:
case WSA_QOS_EOBJLENGTH:
case WSA_QOS_EFLOWCOUNT:
case WSA_QOS_EUNKOWNPSOBJ:
case WSA_QOS_EPOLICYOBJ:
case WSA_QOS_EFLOWDESC:
case WSA_QOS_EPSFLOWSPEC:
case WSA_QOS_EPSFILTERSPEC:
case WSA_QOS_ESDMODEOBJ:
case WSA_QOS_ESHAPERATEOBJ:
case WSA_QOS_RESERVED_PETYPE:
errno = EBOGUSWSOCK;
break;
case WSA_NOT_ENOUGH_MEMORY:
errno = ENOMEM;
break;
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;
case WSAEWOULDBLOCK:
errno = EAGAIN;
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 WSASYSNOTREADY:
case WSAENETDOWN:
errno = ENETDOWN;
break;
case WSAENETUNREACH:
errno = ENETUNREACH;
break;
case WSAENETRESET:
errno = ENETRESET;
break;
case WSAECONNABORTED:
errno = ECONNABORTED;
break;
case WSAECONNRESET:
case WSAEDISCON:
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;
case WSAEPROCLIM:
case WSAEUSERS:
errno = EUSERS;
break;
case WSAEDQUOT:
errno = EDQUOT;
break;
case WSAESTALE:
errno = ESTALE;
break;
case WSAEREMOTE:
errno = EREMOTE;
break;
}
}
int w32_socket(int domain, int type, int protocol) {
SOCKET s = socket(domain, type, protocol);
if(s == INVALID_SOCKET) {
wsock2errno();
return -1;
}
return (int)s;
}
int w32_getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) {
if(getsockopt((SOCKET)sockfd, level, optname, (char *)optval, optlen) == SOCKET_ERROR) {
wsock2errno();
return -1;
}
return 0;
}
int w32_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
if(setsockopt((SOCKET)sockfd, level, optname, (const char*)optval, optlen) == SOCKET_ERROR) {
wsock2errno();
return -1;
}
return 0;
}
int w32_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
if(bind((SOCKET)sockfd, addr, addrlen) == SOCKET_ERROR) {
wsock2errno();
return -1;
}
return 0;
}
int w32_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
if(connect((SOCKET)sockfd, addr, addrlen)) {
wsock2errno();
return -1;
}
return 0;
}
ssize_t w32_send(int sockfd, const void *buf, size_t len, int flags) {
int ret = send((SOCKET)sockfd, (const char *)buf, (int)len, flags);
if(ret == SOCKET_ERROR) {
wsock2errno();
return -1;
}
return (ssize_t)ret;
}
ssize_t w32_recv(int sockfd, void *buf, size_t len, int flags) {
int ret = recv((SOCKET)sockfd, (char *)buf, len, flags);
if(ret == SOCKET_ERROR) {
wsock2errno();
return -1;
}
return (ssize_t)ret;
}
int w32_closesocket(int sockfd) {
if(closesocket((SOCKET)sockfd) == SOCKET_ERROR) {
wsock2errno();
return -1;
}
return 0;
}
struct servent *w32_getservbyname(const char *name, const char *proto) {
return getservbyname(name, proto);
}
int w32_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
return getaddrinfo(node, service, hints, res);
}
void w32_freeaddrinfo(struct addrinfo *res) {
freeaddrinfo(res);
}
const char *w32_inet_ntop(int af, const void *src, char *dst, socklen_t size) {
const char *ret;
if(af != AF_INET) {
errno = EAFNOSUPPORT;
return NULL;
}
ret = inet_ntoa(*(struct in_addr *)src);
if(!ret) {
wsock2errno();
return NULL;
}
if(strlen(ret) >= size) {
errno = ENOSPC;
return NULL;
}
strcpy(dst, ret);
return ret;
}
struct hostent *w32_gethostbyname(const char *name) {
return gethostbyname(name);
}
int w32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
int ret = select(nfds, readfds, writefds, exceptfds, timeout);
if(ret == SOCKET_ERROR) {
wsock2errno();
return -1;
}
return ret;
}
int w32_accept(int sockfd, const struct sockaddr *addr, socklen_t *addrlen) {
int sock;
if((sock = (int)accept((SOCKET)sockfd, addr, addrlen)<0)) {
wsock2errno();
return -1;
}
return sock;
}
int w32_listen(int sockfd, int backlog) {
if(listen((SOCKET)sockfd, backlog)) {
wsock2errno();
return -1;
}
return 0;
}
int w32_shutdown(int sockfd, int how) {
if(shutdown((SOCKET)sockfd, how)) {
wsock2errno();
return -1;
}
return 0;
}
struct w32polldata {
HANDLE setme;
HANDLE event;
HANDLE waiter;
struct pollfd *polldata;
};
static VOID CALLBACK poll_cb(PVOID param, BOOLEAN timedout) {
WSANETWORKEVENTS evt;
struct w32polldata *item = (struct w32polldata *)param;
if(!timedout) {
unsigned int i;
WSAEnumNetworkEvents(item->polldata->fd, item->event, &evt);
for(i=0; i<evt.lNetworkEvents; i++) {
if(evt.iErrorCode[i] & (FD_ACCEPT|FD_READ)) item->polldata->revents |= POLLIN;
if(evt.iErrorCode[i] & FD_CLOSE) item->polldata->revents |= POLLHUP;
}
<<<<<<< HEAD:win32/compat/net.c
if(SetEvent(item->setme)==0) {
int a = GetLastError();
a++;
}
}
}
int poll_with_event(struct pollfd *fds, int nfds, int timeout, HANDLE event) {
HANDLE *setme;
struct w32polldata *items;
unsigned int i, ret = 0;
setme = malloc(2 * sizeof(HANDLE));
setme[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
setme[1] = event;
=======
}
}
int w32_poll(struct pollfd *fds, int nfds, int timeout) {
HANDLE setme = CreateEvent(NULL, TRUE, FALSE, NULL);
struct w32polldata *items;
unsigned int i, ret = 0;
>>>>>>> d29df4cf2d499717dde976c27fa293470cfcf114:win32/compat/net.c
timeout = timeout>=0 ? timeout*1000 : INFINITE;
if(!nfds) {
Sleep(timeout);
return 0;
}
items = malloc(nfds * sizeof(struct w32polldata));
for(i=0; i<nfds; i++) {
items[i].event = CreateEvent(NULL, TRUE, FALSE, NULL);
items[i].polldata = &fds[i];
<<<<<<< HEAD:win32/compat/net.c
items[i].setme = setme[0];
=======
items[i].setme = setme;
>>>>>>> d29df4cf2d499717dde976c27fa293470cfcf114:win32/compat/net.c
if(WSAEventSelect(fds[i].fd, items[i].event, FD_ACCEPT|FD_READ|FD_CLOSE)) {
/* handle error here */
}
if(RegisterWaitForSingleObject(&items[i].waiter, items[i].event, poll_cb, &items[i], timeout, WT_EXECUTEONLYONCE)) {
/* handle errors here */
}
}
<<<<<<< HEAD:win32/compat/net.c
WaitForMultipleObjects(2 - (event == NULL) , setme, FALSE, timeout);
=======
WaitForSingleObject(setme, timeout); /* FIXME - add the pipe here */
>>>>>>> d29df4cf2d499717dde976c27fa293470cfcf114:win32/compat/net.c
for(i=0; i<nfds; i++) {
UnregisterWait(items[i].waiter);
WSAEventSelect(fds[i].fd, items[i].event, 0);
CloseHandle(items[i].event);
ret += (items[i].polldata->revents != 0);
}
free(items);
<<<<<<< HEAD:win32/compat/net.c
CloseHandle(setme[0]);
free(setme);
=======
>>>>>>> d29df4cf2d499717dde976c27fa293470cfcf114:win32/compat/net.c
return ret;
}