diff --git a/nbase/nbase_misc.c b/nbase/nbase_misc.c index 10704f9ad..b341e2f99 100644 --- a/nbase/nbase_misc.c +++ b/nbase/nbase_misc.c @@ -257,7 +257,7 @@ int inheritable_socket(int af, int style, int protocol) { /* WSASocket is just like socket, except that the sockets it creates are inheritable by subprocesses (such as are created by CreateProcess), while those created by socket are not. */ - return WSASocket(af, style, protocol, NULL, 0, WSA_FLAG_OVERLAPPED); + return WSASocket(af, style, protocol, NULL, 0, 0); #else return socket(af, style, protocol); #endif diff --git a/nsock/include/nsock_winconfig.h b/nsock/include/nsock_winconfig.h index aaf5172b4..aa9162e12 100644 --- a/nsock/include/nsock_winconfig.h +++ b/nsock/include/nsock_winconfig.h @@ -104,7 +104,6 @@ /* WSAPoll() isn't available before Vista */ #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) #define HAVE_POLL 1 -#define HAVE_IOCP 1 #endif #endif /* NSOCK_WINCONFIG_H */ diff --git a/nsock/nsock.vcxproj b/nsock/nsock.vcxproj index 60bc95aab..5e4409a0e 100644 --- a/nsock/nsock.vcxproj +++ b/nsock/nsock.vcxproj @@ -186,7 +186,6 @@ - @@ -198,7 +197,6 @@ - @@ -219,7 +217,6 @@ - diff --git a/nsock/src/engine_iocp.c b/nsock/src/engine_iocp.c deleted file mode 100644 index 6e4a00e11..000000000 --- a/nsock/src/engine_iocp.c +++ /dev/null @@ -1,338 +0,0 @@ -/*************************************************************************** - * engine_iocp.c -- I/O Completion Ports based IO engine. * - * * - ***********************IMPORTANT NSOCK LICENSE TERMS*********************** - * * - * The nsock parallel socket event library is (C) 1999-2016 Insecure.Com * - * LLC This library is free software; you may redistribute and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; Version 2. This guarantees * - * your right to use, modify, and redistribute this software under certain * - * conditions. If this license is unacceptable to you, Insecure.Com LLC * - * may be willing to sell alternative licenses (contact * - * sales@insecure.com ). * - * * - * As a special exception to the GPL terms, Insecure.Com LLC grants * - * permission to link the code of this program with any version of the * - * OpenSSL library which is distributed under a license identical to that * - * listed in the included docs/licenses/OpenSSL.txt file, and distribute * - * linked combinations including the two. You must obey the GNU GPL in all * - * respects for all of the code used other than OpenSSL. If you modify * - * this file, you may extend this exception to your version of the file, * - * but you are not obligated to do so. * - * * - * If you received these files with a written license agreement stating * - * terms other than the (GPL) terms above, then that alternative license * - * agreement takes precedence over this comment. * - * * - * Source is provided to this software because we believe users have a * - * right to know exactly what a program is going to do before they run it. * - * This also allows you to audit the software for security holes. * - * * - * Source code also allows you to port Nmap to new platforms, fix bugs, * - * and add new features. You are highly encouraged to send your changes * - * to the dev@nmap.org mailing list for possible incorporation into the * - * main distribution. By sending these changes to Fyodor or one of the * - * Insecure.Org development mailing lists, or checking them into the Nmap * - * source code repository, it is understood (unless you specify otherwise) * - * that you are offering the Nmap Project (Insecure.Com LLC) the * - * unlimited, non-exclusive right to reuse, modify, and relicense the * - * code. Nmap will always be available Open Source, but this is important * - * because the inability to relicense code has caused devastating problems * - * for other Free Software projects (such as KDE and NASM). We also * - * occasionally relicense the code to third parties as discussed above. * - * If you wish to specify special license conditions of your * - * contributions, just say so when you send them. * - * * - * 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 v2.0 for more details * - * (http://www.gnu.org/licenses/gpl-2.0.html). * - * * - ***************************************************************************/ - -/* $Id$ */ - -#if WIN32 -#include "nsock_winconfig.h" -#endif - -#if HAVE_IOCP - -#include -#include - -#include "nsock_internal.h" -#include "nsock_iocp.h" -#include "nsock_log.h" - -#if HAVE_PCAP -#include "nsock_pcap.h" -#endif - - -/* --- ENGINE INTERFACE PROTOTYPES --- */ -static int iocp_init(struct npool *nsp); -static void iocp_destroy(struct npool *nsp); -static int iocp_iod_register(struct npool *nsp, struct niod *iod, int ev); -static int iocp_iod_unregister(struct npool *nsp, struct niod *iod); -static int iocp_iod_modify(struct npool *nsp, struct niod *iod, int ev_set, int ev_clr); -static int iocp_loop(struct npool *nsp, int msec_timeout); - - -/* ---- ENGINE DEFINITION ---- */ -struct io_engine engine_iocp = { - "iocp", - iocp_init, - iocp_destroy, - iocp_iod_register, - iocp_iod_unregister, - iocp_iod_modify, - iocp_loop -}; - - -/* --- INTERNAL PROTOTYPES --- */ -static void iterate_through_event_lists(struct npool *nsp); - -/* defined in nsock_core.c */ -void process_iod_events(struct npool *nsp, struct niod *nsi, int ev); -void process_event(struct npool *nsp, gh_list_t *evlist, struct nevent *nse, int ev); -void process_expired_events(struct npool *nsp); -#if HAVE_PCAP -#ifndef PCAP_CAN_DO_SELECT -int pcap_read_on_nonselect(struct npool *nsp); -#endif -#endif - -/* defined in nsock_event.c */ -void update_first_events(struct nevent *nse); - - -extern struct timeval nsock_tod; - -int iocp_init(struct npool *nsp) { - struct iocp_engine_info *iinfo; - - iinfo = (struct iocp_engine_info *)safe_malloc(sizeof(struct iocp_engine_info)); - - iinfo->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0); - iinfo->capacity = 10; - iinfo->eov = NULL; - iinfo->entries_removed = 0; - iinfo->eov_list = (OVERLAPPED_ENTRY *)safe_malloc(iinfo->capacity * sizeof(OVERLAPPED_ENTRY)); - nsp->engine_data = (void *)iinfo; - - return 1; -} - -void iocp_destroy(struct npool *nsp) { - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nsp->engine_data; - - assert(iinfo != NULL); - - CloseHandle(iinfo->iocp); - free(iinfo->eov_list); - - free(iinfo); -} - -int iocp_iod_register(struct npool *nsp, struct niod *iod, int ev) { - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nsp->engine_data; - HANDLE result; - - assert(!IOD_PROPGET(iod, IOD_REGISTERED)); - iod->watched_events = ev; - result = CreateIoCompletionPort((HANDLE)iod->sd, iinfo->iocp, NULL, 0); - assert(result); - - IOD_PROPSET(iod, IOD_REGISTERED); - return 1; -} - -/* Sadly a socket can't be unassociated with a completion port */ -int iocp_iod_unregister(struct npool *nsp, struct niod *iod) { - - if (IOD_PROPGET(iod, IOD_REGISTERED)) { - /* Nuke all uncompleted operations on that iod */ - CancelIo((HANDLE)iod->sd); - IOD_PROPCLR(iod, IOD_REGISTERED); - } - return 1; -} - -/* Can't do much here for IOCP */ -int iocp_iod_modify(struct npool *nsp, struct niod *iod, int ev_set, int ev_clr) { - int new_events; - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nsp->engine_data; - - assert((ev_set & ev_clr) == 0); - assert(IOD_PROPGET(iod, IOD_REGISTERED)); - - new_events = iod->watched_events; - new_events |= ev_set; - new_events &= ~ev_clr; - - if (new_events == iod->watched_events) - return 1; /* nothing to do */ - - iod->watched_events = new_events; - - return 1; -} - -int iocp_loop(struct npool *nsp, int msec_timeout) { - int event_msecs; /* msecs before an event goes off */ - int combined_msecs; - int sock_err = 0; - BOOL bRet; - int total_events; - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nsp->engine_data; - - assert(msec_timeout >= -1); - - if (nsp->events_pending == 0) - return 0; /* No need to wait on 0 events ... */ - - - struct nevent *nse; - - /* Make sure the preallocated space for the retrieved events is big enough */ - total_events = gh_list_count(&nsp->connect_events) + gh_list_count(&nsp->read_events) + gh_list_count(&nsp->write_events); - if (iinfo->capacity < total_events) { - iinfo->capacity *= 2; - iinfo->eov_list = (OVERLAPPED_ENTRY *)safe_realloc(iinfo->eov_list, iinfo->capacity * sizeof(OVERLAPPED_ENTRY)); - } - - nsock_log_debug_all("wait for events"); - - nse = next_expirable_event(nsp); - if (!nse) - event_msecs = -1; /* None of the events specified a timeout */ - else - event_msecs = MAX(0, TIMEVAL_MSEC_SUBTRACT(nse->timeout, nsock_tod)); - -#if HAVE_PCAP -#ifndef PCAP_CAN_DO_SELECT - /* Force a low timeout when capturing packets on systems where - * the pcap descriptor is not select()able. */ - if (gh_list_count(&nsp->pcap_read_events) > 0) - if (event_msecs > PCAP_POLL_INTERVAL) - event_msecs = PCAP_POLL_INTERVAL; -#endif -#endif - - /* We cast to unsigned because we want -1 to be very high (since it means no - * timeout) */ - combined_msecs = MIN((unsigned)event_msecs, (unsigned)msec_timeout); - -#if HAVE_PCAP -#ifndef PCAP_CAN_DO_SELECT - /* do non-blocking read on pcap devices that doesn't support select() - * If there is anything read, just leave this loop. */ - if (pcap_read_on_nonselect(nsp)) { - /* okay, something was read. */ - } - else -#endif -#endif - { - /* It is mandatory these values are reset before calling GetQueuedCompletionStatusEx */ - iinfo->entries_removed = 0; - memset(iinfo->eov_list, 0, iinfo->capacity * sizeof(OVERLAPPED_ENTRY)); - bRet = GetQueuedCompletionStatusEx(iinfo->iocp, iinfo->eov_list, iinfo->capacity, &iinfo->entries_removed, combined_msecs, FALSE); - } - - gettimeofday(&nsock_tod, NULL); /* Due to iocp delay */ - if (!bRet) { - sock_err = socket_errno(); - if (!iinfo->eov && sock_err != WAIT_TIMEOUT) { - nsock_log_error("nsock_loop error %d: %s", sock_err, socket_strerror(sock_err)); - nsp->errnum = sock_err; - return -1; - } - } - - iterate_through_event_lists(nsp); - - return 1; -} - - -/* ---- INTERNAL FUNCTIONS ---- */ - -/* Iterate through all the event lists (such as connect_events, read_events, -* timer_events, etc) and take action for those that have completed (due to -* timeout, i/o, etc) */ -void iterate_through_event_lists(struct npool *nsp) { - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nsp->engine_data; - - for (int i = 0; i < iinfo->entries_removed; i++) { - - iinfo->eov = (struct extended_overlapped *)iinfo->eov_list[i].lpOverlapped; - /* We can't rely on iinfo->entries_removed to tell us the real number of - * events to process */ - if (!iinfo->eov) - continue; - - - /* Is this the eov of an event that expired? */ - if (iinfo->eov->nse->id != iinfo->eov->nse_id || iinfo->eov->nse->event_done) { - iinfo->eov = NULL; - continue; - } - - struct niod *nsi = iinfo->eov->nse->iod; - struct nevent *nse = iinfo->eov->nse; - gh_list_t *evlist = NULL; - int ev = 0; - - switch (nse->type) { - case NSE_TYPE_CONNECT: - case NSE_TYPE_CONNECT_SSL: - ev = EV_READ; - evlist = &nsp->connect_events; - break; - case NSE_TYPE_READ: - ev = EV_READ; - evlist = &nsp->read_events; - break; - case NSE_TYPE_WRITE: - ev = EV_WRITE; - evlist = &nsp->write_events; - break; - } - assert(evlist); - - process_event(nsp, evlist, nse, ev); - - if (!nse->event_done) - initiate_overlapped_event(nsp, nse); - else - free_eov(nsp, nse->eov); - - if (nse->event_done) { - /* event is done, remove it from the event list and update IOD pointers - * to the first events of each kind */ - update_first_events(nse); - gh_list_remove(evlist, &nse->nodeq_io); - gh_list_append(&nsp->free_events, &nse->nodeq_io); - - if (nse->timeout.tv_sec) - gh_heap_remove(&nsp->expirables, &nse->expire); - } - - if (nsi->state == NSIOD_STATE_DELETED) { - gh_list_remove(&nsp->active_iods, &nsi->nodeq); - gh_list_prepend(&nsp->free_iods, &nsi->nodeq); - } - - iinfo->eov = NULL; - } - - /* iterate through timers and expired events */ - process_expired_events(nsp); -} - -#endif /* HAVE_IOCP */ diff --git a/nsock/src/nsock_connect.c b/nsock/src/nsock_connect.c index f6086631d..ef726351f 100644 --- a/nsock/src/nsock_connect.c +++ b/nsock/src/nsock_connect.c @@ -64,10 +64,6 @@ #include #include -#if HAVE_IOCP -#include "nsock_iocp.h" -#endif - static int mksock_bind_addr(struct npool *ms, struct niod *iod) { int rc; @@ -256,12 +252,6 @@ void nsock_connect_internal(struct npool *ms, struct nevent *nse, int type, int if (&iod->peer != ss) memcpy(&iod->peer, ss, sslen); iod->peerlen = sslen; - -#if HAVE_IOCP - /* The connection will be initiated when the event is added to the iod. */ - if (engine_is_iocp(ms)) - return; -#endif if (connect(iod->sd, (struct sockaddr *)ss, sslen) == -1) { int err = socket_errno(); diff --git a/nsock/src/nsock_core.c b/nsock/src/nsock_core.c index ed88eae3e..ed4e8b87f 100644 --- a/nsock/src/nsock_core.c +++ b/nsock/src/nsock_core.c @@ -86,10 +86,6 @@ #include "nsock_pcap.h" #endif -#if HAVE_IOCP -#include "nsock_iocp.h" -#endif - /* Nsock time of day -- we update this at least once per nsock_loop round (and * after most calls that are likely to block). Other nsock files should grab @@ -291,12 +287,6 @@ static int iod_add_event(struct niod *iod, struct nevent *nse) { default: fatal("Unknown event type (%d) for IOD #%lu\n", nse->type, iod->id); } - -#if HAVE_IOCP - if (engine_is_iocp(nsp)) - initiate_overlapped_event(nsp, nse); -#endif - return 0; } @@ -352,12 +342,6 @@ void handle_connect_result(struct npool *ms, struct nevent *nse, enum nse_status /* First we want to determine whether the socket really is connected */ if (getsockopt(iod->sd, SOL_SOCKET, SO_ERROR, (char *)&optval, &optlen) != 0) optval = socket_errno(); /* Stupid Solaris */ -#if HAVE_IOCP - else if (engine_is_iocp(ms)) { - if (get_overlapped_result(nse->iod, nse, NULL) == -1) - optval = socket_errno(); - } -#endif switch (optval) { case 0: @@ -558,11 +542,6 @@ void handle_write_result(struct npool *ms, struct nevent *nse, enum nse_status s if (iod->ssl) res = SSL_write(iod->ssl, str, bytesleft); else -#endif -#if HAVE_IOCP - if (engine_is_iocp(ms)) { - res = get_overlapped_result(iod, nse, NULL); - } else #endif if (nse->writeinfo.dest.ss_family == AF_UNSPEC) res = send(nse->iod->sd, str, bytesleft, 0); @@ -634,7 +613,7 @@ void handle_timer_result(struct npool *ms, struct nevent *nse, enum nse_status s /* Returns -1 if an error, otherwise the number of newly written bytes */ static int do_actual_read(struct npool *ms, struct nevent *nse) { - char buf[READ_BUFFER_SZ]; + char buf[8192]; int buflen = 0; struct niod *iod = nse->iod; int err = 0; @@ -648,13 +627,8 @@ static int do_actual_read(struct npool *ms, struct nevent *nse) { do { struct sockaddr_storage peer; socklen_t peerlen; + peerlen = sizeof(peer); -#if HAVE_IOCP - if (engine_is_iocp(ms)) { - buflen = get_overlapped_result(iod, nse, buf); - peerlen = 0; - } else -#endif buflen = recvfrom(iod->sd, buf, sizeof(buf), 0, (struct sockaddr *)&peer, &peerlen); /* Using recv() was failing, at least on UNIX, for non-network sockets @@ -1242,11 +1216,6 @@ void process_expired_events(struct npool *nsp) { nse = container_of(hnode, struct nevent, expire); if (!event_timedout(nse)) break; - -#if HAVE_IOCP - if (engine_is_iocp(nsp)) - terminate_overlapped_event(nsp, nse); -#endif gh_heap_pop(&nsp->expirables); process_event(nsp, NULL, nse, EV_NONE); diff --git a/nsock/src/nsock_engines.c b/nsock/src/nsock_engines.c index 7ab92bdbc..dc0e3c97b 100644 --- a/nsock/src/nsock_engines.c +++ b/nsock/src/nsock_engines.c @@ -63,13 +63,6 @@ #include "nsock_internal.h" -#if HAVE_IOCP - extern struct io_engine engine_iocp; - #define ENGINE_IOCP &engine_iocp, -#else - #define ENGINE_IOCP -#endif /* HAVE_IOCP */ - #if HAVE_EPOLL extern struct io_engine engine_epoll; #define ENGINE_EPOLL &engine_epoll, @@ -101,7 +94,6 @@ static struct io_engine *available_engines[] = { ENGINE_EPOLL ENGINE_KQUEUE ENGINE_POLL - ENGINE_IOCP ENGINE_SELECT NULL }; @@ -153,9 +145,6 @@ int nsock_set_default_engine(char *engine) { const char *nsock_list_engines(void) { return -#if HAVE_IOCP - "iocp " -#endif #if HAVE_EPOLL "epoll " #endif diff --git a/nsock/src/nsock_internal.h b/nsock/src/nsock_internal.h index fd519822d..7927b74e5 100644 --- a/nsock/src/nsock_internal.h +++ b/nsock/src/nsock_internal.h @@ -110,8 +110,6 @@ /* ------------------- CONSTANTS ------------------- */ -#define READ_BUFFER_SZ 8192 - enum nsock_read_types { NSOCK_READLINES, NSOCK_READBYTES, @@ -178,11 +176,6 @@ struct npool { gh_list_t free_iods; /* When an event is deleted, we stick it here for later reuse */ gh_list_t free_events; - -#if HAVE_IOCP - gh_list_t active_eovs; - gh_list_t free_eovs; -#endif /* Number of events pending (total) on all lists */ int events_pending; @@ -367,10 +360,6 @@ struct nevent { * that other crap */ unsigned int event_done: 1; unsigned int eof: 1; - -#if HAVE_IOCP - struct extended_overlapped *eov; -#endif }; @@ -513,9 +502,5 @@ static inline struct nevent *lnode_nevent2(gh_lnode_t *lnode) { return container_of(lnode, struct nevent, nodeq_pcap); } -static inline int engine_is_iocp(struct npool *nsp) { - return !strcmp(nsp->engine->name, "iocp"); -} - #endif /* NSOCK_INTERNAL_H */ diff --git a/nsock/src/nsock_iocp.c b/nsock/src/nsock_iocp.c deleted file mode 100644 index 8b27b09ae..000000000 --- a/nsock/src/nsock_iocp.c +++ /dev/null @@ -1,388 +0,0 @@ -/*************************************************************************** - * nsock_iocp.c -- This contains operations required by IOCP * - * * - ***********************IMPORTANT NSOCK LICENSE TERMS*********************** - * * - * The nsock parallel socket event library is (C) 1999-2016 Insecure.Com * - * LLC This library is free software; you may redistribute and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; Version 2. This guarantees * - * your right to use, modify, and redistribute this software under certain * - * conditions. If this license is unacceptable to you, Insecure.Com LLC * - * may be willing to sell alternative licenses (contact * - * sales@insecure.com ). * - * * - * As a special exception to the GPL terms, Insecure.Com LLC grants * - * permission to link the code of this program with any version of the * - * OpenSSL library which is distributed under a license identical to that * - * listed in the included docs/licenses/OpenSSL.txt file, and distribute * - * linked combinations including the two. You must obey the GNU GPL in all * - * respects for all of the code used other than OpenSSL. If you modify * - * this file, you may extend this exception to your version of the file, * - * but you are not obligated to do so. * - * * - * If you received these files with a written license agreement stating * - * terms other than the (GPL) terms above, then that alternative license * - * agreement takes precedence over this comment. * - * * - * Source is provided to this software because we believe users have a * - * right to know exactly what a program is going to do before they run it. * - * This also allows you to audit the software for security holes. * - * * - * Source code also allows you to port Nmap to new platforms, fix bugs, * - * and add new features. You are highly encouraged to send your changes * - * to the dev@nmap.org mailing list for possible incorporation into the * - * main distribution. By sending these changes to Fyodor or one of the * - * Insecure.Org development mailing lists, or checking them into the Nmap * - * source code repository, it is understood (unless you specify otherwise) * - * that you are offering the Nmap Project (Insecure.Com LLC) the * - * unlimited, non-exclusive right to reuse, modify, and relicense the * - * code. Nmap will always be available Open Source, but this is important * - * because the inability to relicense code has caused devastating problems * - * for other Free Software projects (such as KDE and NASM). We also * - * occasionally relicense the code to third parties as discussed above. * - * If you wish to specify special license conditions of your * - * contributions, just say so when you send them. * - * * - * 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 v2.0 for more details * - * (http://www.gnu.org/licenses/gpl-2.0.html). * - * * - ***************************************************************************/ - -/* $Id$ */ - - -#if WIN32 -#include "nsock_winconfig.h" -#endif - -#if HAVE_IOCP - -#include -#include - -#include "nsock_internal.h" -#include "nsock_iocp.h" -#include "nsock_log.h" - - -static int errcode_is_failure(int err) { -#ifndef WIN32 - return err != EINTR && err != EAGAIN && err != EBUSY; -#else - return err != EINTR && err != EAGAIN && err != WSA_IO_PENDING && err != ERROR_NETNAME_DELETED; -#endif -} - -static int map_faulty_errors(int err) { - /* This actually happens https://svn.boost.org/trac/boost/ticket/10744 */ - switch (err) { - case ERROR_NETWORK_UNREACHABLE: return WSAENETUNREACH; - case ERROR_HOST_UNREACHABLE: return WSAEHOSTUNREACH; - case ERROR_CONNECTION_REFUSED: return WSAECONNREFUSED; - case ERROR_SEM_TIMEOUT: return WSAETIMEDOUT; - } - return err; -} - -static struct extended_overlapped *new_eov(struct npool *nsp, struct nevent *nse) { - struct extended_overlapped *eov; - gh_lnode_t *lnode; - - if(nse->eov) { - memset(&nse->eov->ov, 0, sizeof(OVERLAPPED)); - return nse->eov; - } - - lnode = gh_list_pop(&nsp->free_eovs); - if (!lnode) - eov = (struct extended_overlapped *)safe_malloc(sizeof(struct extended_overlapped)); - else - eov = container_of(lnode, struct extended_overlapped, nodeq); - - memset(eov, 0, sizeof(struct extended_overlapped)); - nse->eov = eov; - eov->nse = nse; - eov->nse_id = nse->id; - eov->err = 0; - gh_list_prepend(&nsp->active_eovs, &eov->nodeq); - - /* Make the read buffer equal to the size of the buffer in do_actual_read() */ - if (nse->type == NSE_TYPE_READ && !eov->readbuf) - eov->readbuf = (char*)safe_malloc(READ_BUFFER_SZ * sizeof(char*)); - - return eov; -} - -static void call_connect_overlapped(struct npool *nsp, struct nevent *nse) { - BOOL ok; - DWORD numBytes = 0; - SOCKET sock = nse->iod->sd; - GUID guid = WSAID_CONNECTEX; - struct sockaddr_in addr; - LPFN_CONNECTEX ConnectExPtr = NULL; - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nse->iod->nsp->engine_data; - struct extended_overlapped *eov = new_eov(nsp, nse); - int ret; - struct sockaddr_storage *ss = &nse->iod->peer; - size_t sslen = nse->iod->peerlen; - - if (nse->iod->lastproto != IPPROTO_TCP) { - if (connect(sock, (struct sockaddr *)ss, sslen) == -1) { - int err = socket_errno(); - nse->event_done = 1; - nse->status = NSE_STATUS_ERROR; - nse->errnum = err; - - free_eov(nsp, eov); - } else { - BOOL bRet = PostQueuedCompletionStatus(*(HANDLE *)iinfo, -1, (ULONG_PTR)nse->iod, (LPOVERLAPPED)eov); - assert(bRet); - } - return; - } - - ret = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, - (void*)&guid, sizeof(guid), (void*)&ConnectExPtr, sizeof(ConnectExPtr), - &numBytes, NULL, NULL); - assert(!ret); - - /* ConnectEx doesn't automatically bind the socket */ - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = 0; - if (!nse->iod->locallen) { - ret = bind(sock, (SOCKADDR*)&addr, sizeof(addr)); - if(ret) { - int err = socket_errno(); - nse->event_done = 1; - nse->status = NSE_STATUS_ERROR; - nse->errnum = err; - - free_eov(nsp, eov); - return; - } - } - - ok = ConnectExPtr(sock, (SOCKADDR*)ss, sslen, NULL, 0, NULL, (LPOVERLAPPED)eov); - if (!ok) { - int err = socket_errno(); - if (err != ERROR_IO_PENDING) { - nse->event_done = 1; - nse->status = NSE_STATUS_ERROR; - nse->errnum = err; - - free_eov(nsp, eov); - } - } -} - -static void call_read_overlapped(struct nevent *nse) { - DWORD flags = 0; - int err = 0; - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nse->iod->nsp->engine_data; - - struct extended_overlapped *eov = new_eov(nse->iod->nsp, nse); - - eov->wsabuf.buf = eov->readbuf; - eov->wsabuf.len = 8192; - - err = WSARecvFrom(nse->iod->sd, &eov->wsabuf, 1, NULL, &flags, - (struct sockaddr *)&nse->iod->peer, (LPINT)&nse->iod->peerlen, (LPOVERLAPPED)eov, NULL); - if (err) { - err = socket_errno(); - if (errcode_is_failure(err)) { - eov->err = err; - BOOL bRet = PostQueuedCompletionStatus(iinfo->iocp, -1, (ULONG_PTR)nse->iod, (LPOVERLAPPED)eov); - assert(bRet); - } - } -} - -static void call_write_overlapped(struct nevent *nse) { - int err; - char *str; - int bytesleft; - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nse->iod->nsp->engine_data; - - struct extended_overlapped *eov = new_eov(nse->iod->nsp, nse); - - str = fs_str(&nse->iobuf) + nse->writeinfo.written_so_far; - bytesleft = fs_length(&nse->iobuf) - nse->writeinfo.written_so_far; - - eov->wsabuf.buf = str; - eov->wsabuf.len = bytesleft; - - if (nse->writeinfo.dest.ss_family == AF_UNSPEC) - err = WSASend(nse->iod->sd, &eov->wsabuf, 1, NULL, 0, (LPWSAOVERLAPPED)eov, NULL); - else - err = WSASendTo(nse->iod->sd, &eov->wsabuf, 1, NULL, 0, - (struct sockaddr *)&nse->writeinfo.dest, (int)nse->writeinfo.destlen, - (LPWSAOVERLAPPED)eov, NULL); - if (err) { - err = socket_errno(); - if (errcode_is_failure(err)) { - eov->err = err; - BOOL bRet = PostQueuedCompletionStatus(iinfo->iocp, -1, (ULONG_PTR)nse->iod, (LPOVERLAPPED)eov); - assert(bRet); - } - } -} - -/* Either initiate a I/O read or force a SSL_read */ -static void initiate_read(struct npool *nsp, struct nevent *nse) { - BOOL bRet; - - struct extended_overlapped *eov; - - if (!strcmp(nsp->engine->name, "iocp")) { - if (!nse->iod->ssl) - call_read_overlapped(nse); - else { - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nsp->engine_data; - eov = new_eov(nse->iod->nsp, nse); - bRet = PostQueuedCompletionStatus(iinfo->iocp, 0, (ULONG_PTR)nse->iod, (LPOVERLAPPED)eov); - assert(bRet); - } - } -} - -/* Either initiate a I/O write or force a SSL_write */ -static void initiate_write(struct npool *nsp, struct nevent *nse) { - BOOL bRet; - - struct extended_overlapped *eov; - - if (!strcmp(nsp->engine->name, "iocp")) { - if (!nse->iod->ssl) - call_write_overlapped(nse); - else { - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nsp->engine_data; - eov = new_eov(nse->iod->nsp, nse); - bRet = PostQueuedCompletionStatus(iinfo->iocp, 0, (ULONG_PTR)nse->iod, (LPOVERLAPPED)eov); - assert(bRet); - } - } -} - -/* Force a PCAP read */ -static void initiate_pcap_read(struct npool *nsp, struct nevent *nse) { - BOOL bRet; - - struct extended_overlapped *eov; - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nsp->engine_data; - - eov = new_eov(nse->iod->nsp, nse); - bRet = PostQueuedCompletionStatus(iinfo->iocp, 0, (ULONG_PTR)nse->iod, (LPOVERLAPPED)eov); - assert(bRet); -} - -static void initiate_connect(struct npool *nsp, struct nevent *nse) { - int sslconnect_inprogress = 0; - BOOL bRet; - struct extended_overlapped *eov; - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nsp->engine_data; - -#if HAVE_OPENSSL - sslconnect_inprogress = nse->type == NSE_TYPE_CONNECT_SSL && nse->iod && - (nse->sslinfo.ssl_desire == SSL_ERROR_WANT_READ || - nse->sslinfo.ssl_desire == SSL_ERROR_WANT_WRITE); -#endif - - if (sslconnect_inprogress) { - eov = new_eov(nse->iod->nsp, nse); - bRet = PostQueuedCompletionStatus(iinfo->iocp, 0, (ULONG_PTR)nse->iod, (LPOVERLAPPED)eov); - assert(bRet); - } - else - call_connect_overlapped(nsp, nse); -} - -/* Start the overlapped I/O operation */ -void initiate_overlapped_event(struct npool *nsp, struct nevent *nse) { - if (!engine_is_iocp(nsp)) - return; - - switch (nse->type) { - case NSE_TYPE_CONNECT: - case NSE_TYPE_CONNECT_SSL: - initiate_connect(nsp, nse); - break; - case NSE_TYPE_READ: - initiate_read(nsp, nse); - break; - case NSE_TYPE_WRITE: - initiate_write(nsp, nse); - break; -#if HAVE_PCAP - case NSE_TYPE_PCAP_READ: - initiate_pcap_read(nsp, nse); - break; -#endif - default: fatal("Event type(%d) not supported by engine IOCP\n", nse->type); - } -} - -/* Terminate an overlapped I/O operation that expired */ -void terminate_overlapped_event(struct npool *nsp, struct nevent *nse) { - if (!HasOverlappedIoCompleted((LPOVERLAPPED)nse->eov)) - CancelIoEx((HANDLE)nse->iod->sd, (LPOVERLAPPED)nse->eov); -} - -/* Retrieve the ammount of bytes transferred or set the appropriate error */ -int get_overlapped_result(struct niod *iod, struct nevent *nse, char *buf) { - DWORD dwRes = 0; - int err; - struct npool *nsp = nse->iod->nsp; - static struct extended_overlapped *old_eov = NULL; - struct iocp_engine_info *iinfo = (struct iocp_engine_info *)nsp->engine_data; - - struct extended_overlapped *eov = iinfo->eov; - - if (eov->err) { - SetLastError(map_faulty_errors(eov->err)); - return -1; - } - - if (!GetOverlappedResult((HANDLE)iod->sd, (LPOVERLAPPED)eov, &dwRes, FALSE)) { - err = socket_errno(); - if (errcode_is_failure(err)) { - SetLastError(map_faulty_errors(err)); - return -1; - } - } - - if (nse->type == NSE_TYPE_READ && buf) - memcpy(buf, eov->wsabuf.buf, dwRes); - - /* If the read buffer wasn't big enough, subsequent calls from do_actual_read will make us - read with recvfrom the rest of the returned data */ - if (nse->type == NSE_TYPE_READ && dwRes == eov->wsabuf.len && old_eov == eov) { - struct sockaddr_storage peer; - socklen_t peerlen = sizeof(peer); - dwRes = recvfrom(iod->sd, buf, sizeof(buf), 0, (struct sockaddr *)&peer, &peerlen); - } - - if (!nse->type == NSE_TYPE_READ || (nse->type == NSE_TYPE_READ && dwRes < eov->wsabuf.len)) { - old_eov = NULL; - } else if (nse->type == NSE_TYPE_READ && dwRes == eov->wsabuf.len) { - old_eov = eov; - } - - return dwRes; -} - -void free_eov(struct npool *nsp, struct extended_overlapped *eov) { - if (eov->readbuf) { - free(eov->readbuf); - eov->readbuf = NULL; - } - gh_list_remove(&nsp->active_eovs, &eov->nodeq); - gh_list_prepend(&nsp->free_eovs, &eov->nodeq); -} - -#endif /* HAVE_IOCP */ diff --git a/nsock/src/nsock_iocp.h b/nsock/src/nsock_iocp.h deleted file mode 100644 index 4c4e9ade4..000000000 --- a/nsock/src/nsock_iocp.h +++ /dev/null @@ -1,117 +0,0 @@ -/*************************************************************************** - * nsock_iocp.h -- Header for the overlapped operations in nsock_iocp.c. * - * * - ***********************IMPORTANT NSOCK LICENSE TERMS*********************** - * * - * The nsock parallel socket event library is (C) 1999-2016 Insecure.Com * - * LLC This library is free software; you may redistribute and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; Version 2. This guarantees * - * your right to use, modify, and redistribute this software under certain * - * conditions. If this license is unacceptable to you, Insecure.Com LLC * - * may be willing to sell alternative licenses (contact * - * sales@insecure.com ). * - * * - * As a special exception to the GPL terms, Insecure.Com LLC grants * - * permission to link the code of this program with any version of the * - * OpenSSL library which is distributed under a license identical to that * - * listed in the included docs/licenses/OpenSSL.txt file, and distribute * - * linked combinations including the two. You must obey the GNU GPL in all * - * respects for all of the code used other than OpenSSL. If you modify * - * this file, you may extend this exception to your version of the file, * - * but you are not obligated to do so. * - * * - * If you received these files with a written license agreement stating * - * terms other than the (GPL) terms above, then that alternative license * - * agreement takes precedence over this comment. * - * * - * Source is provided to this software because we believe users have a * - * right to know exactly what a program is going to do before they run it. * - * This also allows you to audit the software for security holes. * - * * - * Source code also allows you to port Nmap to new platforms, fix bugs, * - * and add new features. You are highly encouraged to send your changes * - * to the dev@nmap.org mailing list for possible incorporation into the * - * main distribution. By sending these changes to Fyodor or one of the * - * Insecure.Org development mailing lists, or checking them into the Nmap * - * source code repository, it is understood (unless you specify otherwise) * - * that you are offering the Nmap Project (Insecure.Com LLC) the * - * unlimited, non-exclusive right to reuse, modify, and relicense the * - * code. Nmap will always be available Open Source, but this is important * - * because the inability to relicense code has caused devastating problems * - * for other Free Software projects (such as KDE and NASM). We also * - * occasionally relicense the code to third parties as discussed above. * - * If you wish to specify special license conditions of your * - * contributions, just say so when you send them. * - * * - * 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 v2.0 for more details * - * (http://www.gnu.org/licenses/gpl-2.0.html). * - * * - ***************************************************************************/ - -#ifndef NSOCK_IOCP_H -#define NSOCK_IOCP_H - -#include "nsock_internal.h" -#ifdef HAVE_IOCP - -/* - * Engine specific data structure - */ -struct iocp_engine_info { - /* The handle to the Completion Port*/ - HANDLE iocp; - - /* We put the current eov to be processed here in order to be retrieved by nsock_core */ - struct extended_overlapped *eov; - - /* The overlapped_entry list used to retrieve completed packets from the port */ - OVERLAPPED_ENTRY *eov_list; - unsigned long capacity; - - /* How many Completion Packets we actually retreieved */ - unsigned long entries_removed; -}; - -struct extended_overlapped { - /* Overlapped structure used for overlapped operations */ - OVERLAPPED ov; - - /* Did we get an error when we initiated the operation? - Put the error code here and post it to the main loop */ - int err; - - /* The event may have expired and was recycled, we can't trust - a pointer to the nevent structure to tell us the real nevent */ - nsock_event_id nse_id; - - /* A pointer to the event */ - struct nevent *nse; - - /* Needed for WSARecv/WSASend */ - WSABUF wsabuf; - - /* This is the buffer we will read data in */ - char *readbuf; - - /* The struct npool keeps track of EOVs that have been allocated so that it - * can destroy them if the msp is deleted. This pointer makes it easy to - * remove this struct extended_overlapped from the allocated list when necessary */ - gh_lnode_t nodeq; - -}; - - -void initiate_overlapped_event(struct npool *nsp, struct nevent *nse); - -void terminate_overlapped_event(struct npool *nsp, struct nevent *nse); - -int get_overlapped_result(struct niod *iod, struct nevent *nse, char *buf); - -void free_eov(struct npool *nsp, struct extended_overlapped *eov); - -#endif /* HAVE_IOCP */ -#endif /* NSOCK_IOCP_H */ diff --git a/nsock/src/nsock_pool.c b/nsock/src/nsock_pool.c index fe7decdd6..e9330d50b 100644 --- a/nsock/src/nsock_pool.c +++ b/nsock/src/nsock_pool.c @@ -71,10 +71,6 @@ #endif #include -#if HAVE_IOCP -#include "nsock_iocp.h" -#endif - extern struct timeval nsock_tod; @@ -176,11 +172,6 @@ nsock_pool nsock_pool_new(void *userdata) { /* initialize caches */ gh_list_init(&nsp->free_iods); gh_list_init(&nsp->free_events); - -#if HAVE_IOCP - gh_list_init(&nsp->active_eovs); - gh_list_init(&nsp->free_eovs); -#endif nsp->next_event_serial = 1; @@ -287,33 +278,10 @@ void nsock_pool_delete(nsock_pool ms_pool) { nse = lnode_nevent(current); free(nse); } - -#if HAVE_IOCP - struct extended_overlapped *eov; - - while ((current = gh_list_pop(&nsp->active_eovs))) { - eov = container_of(current, struct extended_overlapped, nodeq); - if (eov->readbuf) { - free(eov->readbuf); - eov->readbuf = NULL; - } - free(eov); - } - - while ((current = gh_list_pop(&nsp->free_eovs))) { - eov = container_of(current, struct extended_overlapped, nodeq); - free(eov); - } -#endif gh_list_free(&nsp->active_iods); gh_list_free(&nsp->free_iods); gh_list_free(&nsp->free_events); - -#if HAVE_IOCP - gh_list_free(&nsp->active_eovs); - gh_list_free(&nsp->free_eovs); -#endif nsock_engine_destroy(nsp);