Index: nsock/include/nsock_config.h.in
===================================================================
--- nsock/include/nsock_config.h.in	(revision 28229)
+++ nsock/include/nsock_config.h.in	(working copy)
@@ -76,4 +76,5 @@
 #undef HAVE_SSL_SET_TLSEXT_HOST_NAME
 
 #undef HAVE_EPOLL
+#undef HAVE_POLL
 
Index: nsock/src/configure
===================================================================
--- nsock/src/configure	(revision 28229)
+++ nsock/src/configure	(working copy)
@@ -3115,7 +3115,13 @@
 fi
 done
 
+ac_fn_c_check_func "$LINENO" "poll" "ac_cv_func_poll"
+if test "x$ac_cv_func_poll" = xyes; then :
+  $as_echo "#define HAVE_POLL 1" >>confdefs.h
 
+fi
+
+
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
Index: nsock/src/Makefile.in
===================================================================
--- nsock/src/Makefile.in	(revision 28229)
+++ nsock/src/Makefile.in	(working copy)
@@ -27,9 +27,9 @@
 
 TARGET = libnsock.a
 
-SRCS = error.c filespace.c gh_list.c nsock_connect.c nsock_core.c nsock_iod.c nsock_read.c nsock_timers.c nsock_write.c nsock_ssl.c nsock_event.c nsock_pool.c netutils.c nsock_pcap.c nsock_engines.c engine_select.c engine_epoll.c @COMPAT_SRCS@
+SRCS = error.c filespace.c gh_list.c nsock_connect.c nsock_core.c nsock_iod.c nsock_read.c nsock_timers.c nsock_write.c nsock_ssl.c nsock_event.c nsock_pool.c netutils.c nsock_pcap.c nsock_engines.c engine_select.c engine_epoll.c engine_poll.c @COMPAT_SRCS@
 
-OBJS = error.o filespace.o gh_list.o nsock_connect.o nsock_core.o nsock_iod.o nsock_read.o nsock_timers.o nsock_write.o nsock_ssl.o nsock_event.o nsock_pool.o netutils.o nsock_pcap.o nsock_engines.o engine_select.o engine_epoll.o @COMPAT_OBJS@
+OBJS = error.o filespace.o gh_list.o nsock_connect.o nsock_core.o nsock_iod.o nsock_read.o nsock_timers.o nsock_write.o nsock_ssl.o nsock_event.o nsock_pool.o netutils.o nsock_pcap.o nsock_engines.o engine_select.o engine_epoll.o engine_poll.o @COMPAT_OBJS@
 
 DEPS = error.h filespace.h gh_list.h nsock_internal.h netutils.h nsock_pcap.h ../include/nsock.h $(NBASEDIR)/libnbase.a
 
Index: nsock/src/configure.ac
===================================================================
--- nsock/src/configure.ac	(revision 28229)
+++ nsock/src/configure.ac	(working copy)
@@ -108,6 +108,7 @@
 fi
 
 AC_CHECK_FUNCS(epoll_create epoll_ctl epoll_wait, [AC_DEFINE(HAVE_EPOLL)], )
+AC_CHECK_FUNC(poll, [AC_DEFINE(HAVE_POLL)], )
 
 dnl Checks for programs.
 AC_PROG_CC
Index: nsock/src/nsock_engines.c
===================================================================
--- nsock/src/nsock_engines.c	(revision 28229)
+++ nsock/src/nsock_engines.c	(working copy)
@@ -71,6 +71,13 @@
   #define ENGINE_EPOLL
 #endif /* HAVE_EPOLL */
 
+#if HAVE_POLL
+  extern struct io_engine engine_poll;
+  #define ENGINE_POLL &engine_poll,
+#else
+  #define ENGINE_POLL
+#endif /* HAVE_POLL */
+
 /* select() based engine is the fallback engine, we assume it's always available */
 extern struct io_engine engine_select;
 #define ENGINE_SELECT &engine_select,
@@ -79,6 +86,7 @@
  * available on your system. Engines must be sorted by order of preference */
 static struct io_engine *available_engines[] = {
   ENGINE_EPOLL
+  ENGINE_POLL
   ENGINE_SELECT
   NULL
 };
Index: nsock/src/engine_poll.c
===================================================================
--- nsock/src/engine_poll.c	(revision 0)
+++ nsock/src/engine_poll.c	(revision 0)
@@ -0,0 +1,405 @@
+/***************************************************************************
+ * engine_poll.c -- poll(2) based IO engine.                               *
+ *                                                                         *
+ ***********************IMPORTANT NSOCK LICENSE TERMS***********************
+ *                                                                         *
+ * The nsock parallel socket event library is (C) 1999-2012 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 (none     *
+ * have been found so far).                                                *
+ *                                                                         *
+ * 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 nmap-dev () insecure org for possible incorporation into the main       *
+ * distribution.  By sending these changes to Fyodor or one of the         *
+ * Insecure.Org development mailing lists, it is assumed 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: engine_poll.c 28089 2012-02-17 10:51:01Z henri $ */
+
+#ifndef WIN32
+/* Allow the use of POLLRDHUP, if available. */
+#define _GNU_SOURCE
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "nsock_config.h"
+#endif
+
+#if HAVE_POLL
+
+#ifndef WIN32
+#include <poll.h>
+#else
+#include <Winsock2.h>
+#endif /* ^WIN32 */
+
+#include "nsock_internal.h"
+
+#if HAVE_PCAP
+#include "nsock_pcap.h"
+#endif
+
+#define SD_CACHE_INIT_SIZE 1024
+
+#ifdef WIN32
+  #define Poll    WSAPoll
+  #define POLLFD  WSAPOLLFD
+#else
+  #define Poll    poll
+  #define POLLFD  struct pollfd
+#endif
+
+#define POLL_R_FLAGS (POLLIN | POLLPRI)
+#define POLL_W_FLAGS POLLOUT
+#ifdef POLLRDHUP
+  #define POLL_X_FLAGS (POLLERR | POLLHUP | POLLRDHUP)
+#else
+  /* POLLRDHUP was introduced later and might be unavailable on older systems. */
+  #define POLL_X_FLAGS (POLLERR | POLLHUP)
+#endif /* POLLRDHUP */
+
+#define LOWER_MAX_FD(pinfo) \
+  do {  \
+    pinfo->max_fd--;  \
+  } while (pinfo->max_fd > 0 && pinfo->events[pinfo->max_fd].fd == -1);
+
+
+/* --- ENGINE INTERFACE PROTOTYPES --- */
+static int poll_init(mspool *nsp);
+static void poll_destroy(mspool *nsp);
+static int poll_iod_register(mspool *nsp, msiod *iod, int ev);
+static int poll_iod_unregister(mspool *nsp, msiod *iod);
+static int poll_iod_modify(mspool *nsp, msiod *iod, int ev_set, int ev_clr);
+static int poll_loop(mspool *nsp, int msec_timeout);
+
+
+/* ---- ENGINE DEFINITION ---- */
+struct io_engine engine_poll = {
+  "poll",
+  poll_init,
+  poll_destroy,
+  poll_iod_register,
+  poll_iod_unregister,
+  poll_iod_modify,
+  poll_loop
+};
+
+
+/* --- INTERNAL PROTOTYPES --- */
+static void iterate_through_event_lists(mspool *nsp);
+
+/* defined in nsock_core.c */
+void process_iod_events(mspool *nsp, msiod *nsi, int ev);
+void process_event(mspool *nsp, gh_list *evlist, msevent *nse, int ev);
+#if HAVE_PCAP
+int pcap_read_on_nonselect(mspool *nsp);
+#endif
+
+/* defined in nsock_event.c */
+void update_first_events(msevent *nse);
+
+
+extern struct timeval nsock_tod;
+
+
+/*
+ * Engine specific data structure
+ */
+struct poll_engine_info {
+  int capacity;
+  int max_fd;
+  /* index of the highest poll event */
+  POLLFD *events;
+};
+
+
+int poll_init(mspool *nsp) {
+  int i;
+  struct poll_engine_info *pinfo;
+
+  pinfo = (struct poll_engine_info *)safe_malloc(sizeof(struct poll_engine_info));
+  pinfo->capacity = SD_CACHE_INIT_SIZE;
+  pinfo->max_fd = -1;
+
+  pinfo->events = (POLLFD *)safe_malloc(sizeof(POLLFD) * pinfo->capacity);
+  for (i = 0; i < pinfo->capacity; i++) {
+    pinfo->events[i].fd = -1;
+    pinfo->events[i].events = 0;
+    pinfo->events[i].revents = 0;
+  }
+
+  nsp->engine_data = (void *)pinfo;
+
+  return 1;
+}
+
+void poll_destroy(mspool *nsp) {
+  struct poll_engine_info *pinfo = (struct poll_engine_info *)nsp->engine_data;
+
+  assert(pinfo != NULL);
+  free(pinfo->events);
+  free(pinfo);
+}
+
+int poll_iod_register(mspool *nsp, msiod *iod, int ev) {
+  int sd;
+  struct poll_engine_info *pinfo = (struct poll_engine_info *)nsp->engine_data;
+
+  assert(!IOD_PROPGET(iod, IOD_REGISTERED));
+
+  iod->watched_events = ev;
+
+  sd = nsi_getsd(iod);
+  while (pinfo->capacity < sd + 1) {
+    int newcap = pinfo->capacity * 2;
+
+    pinfo->events = (POLLFD *)safe_realloc(pinfo->events, sizeof(POLLFD) * newcap);
+    while (newcap-- > pinfo->capacity) {
+      pinfo->events[newcap].fd = -1;
+      pinfo->events[newcap].events = 0;
+      pinfo->events[newcap].revents = 0;
+    }
+    pinfo->capacity *= 2;
+  }
+  pinfo->max_fd = MAX(pinfo->max_fd, sd);
+
+  pinfo->events[sd].fd = sd;
+  pinfo->events[sd].events = 0;
+  pinfo->events[sd].revents = 0;
+
+  if (ev & EV_READ)
+    pinfo->events[sd].events |= POLL_R_FLAGS;
+  if (ev & EV_WRITE)
+    pinfo->events[sd].events |= POLL_W_FLAGS;
+  if (ev & EV_EXCEPT)
+    pinfo->events[sd].events |= POLL_X_FLAGS;
+
+  IOD_PROPSET(iod, IOD_REGISTERED);
+  return 1;
+}
+
+int poll_iod_unregister(mspool *nsp, msiod *iod) {
+  iod->watched_events = EV_NONE;
+
+  /* some IODs can be unregistered here if they're associated to an event that was
+   * immediately completed */
+  if (IOD_PROPGET(iod, IOD_REGISTERED)) {
+    struct poll_engine_info *pinfo = (struct poll_engine_info *)nsp->engine_data;
+    int sd;
+
+    sd = nsi_getsd(iod);
+    pinfo->events[sd].fd = -1;
+    pinfo->events[sd].events = 0;
+    pinfo->events[sd].revents = 0;
+
+    if (pinfo->max_fd == sd) {
+      LOWER_MAX_FD(pinfo);
+    }
+
+    IOD_PROPCLR(iod, IOD_REGISTERED);
+  }
+  return 1;
+}
+
+int poll_iod_modify(mspool *nsp, msiod *iod, int ev_set, int ev_clr) {
+  int sd;
+  int new_events;
+  struct poll_engine_info *pinfo = (struct poll_engine_info *)nsp->engine_data;
+
+  assert((ev_set & ev_clr) == 0);
+
+  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;
+
+  sd = nsi_getsd(iod);
+
+  pinfo->events[sd].fd = sd;
+  pinfo->events[sd].events = 0;
+
+  /* regenerate the current set of events for this IOD */
+  if (iod->watched_events & EV_READ)
+    pinfo->events[sd].events |= POLL_R_FLAGS;
+  if (iod->watched_events & EV_WRITE)
+    pinfo->events[sd].events |= POLL_W_FLAGS;
+  if (iod->watched_events & EV_EXCEPT)
+    pinfo->events[sd].events |= POLL_X_FLAGS;
+
+  return 1;
+}
+
+int poll_loop(mspool *nsp, int msec_timeout) {
+  int results_left;
+  int event_msecs; /* msecs before an event goes off */
+  int combined_msecs;
+  int sock_err = 0;
+  struct poll_engine_info *pinfo = (struct poll_engine_info *)nsp->engine_data;
+
+  assert(msec_timeout >= -1);
+
+  if (nsp->events_pending == 0)
+    return 0; /* No need to wait on 0 events ... */
+
+  do {
+    if (nsp->tracelevel > 6)
+      nsock_trace(nsp, "wait_for_events");
+
+    if (nsp->next_ev.tv_sec == 0)
+      event_msecs = -1; /* None of the events specified a timeout */
+    else
+      event_msecs = MAX(0, TIMEVAL_MSEC_SUBTRACT(nsp->next_ev, 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
+    /* 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
+    {
+      if (pinfo->max_fd > -1)
+        results_left = Poll(pinfo->events, pinfo->max_fd + 1, combined_msecs);
+      else
+        results_left = 0;
+
+      if (results_left == -1)
+        sock_err = socket_errno();
+    }
+
+    gettimeofday(&nsock_tod, NULL); /* Due to poll delay */
+  } while (results_left == -1 && sock_err == EINTR); /* repeat only if signal occurred */
+
+  if (results_left == -1 && sock_err != EINTR) {
+    nsock_trace(nsp, "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(mspool *nsp) {
+  gh_list_elem *current, *next, *last, *timer_last;
+  struct poll_engine_info *pinfo = (struct poll_engine_info *)nsp->engine_data;
+
+  /* Clear it -- We will find the next event as we go through the list */
+  nsp->next_ev.tv_sec = 0;
+
+  last = GH_LIST_LAST_ELEM(&nsp->active_iods);
+  timer_last = GH_LIST_LAST_ELEM(&nsp->timer_events);
+
+  for (current = GH_LIST_FIRST_ELEM(&nsp->active_iods);
+       current != NULL && GH_LIST_ELEM_PREV(current) != last; current = next) {
+    msiod *nsi = (msiod *)GH_LIST_ELEM_DATA(current);
+    
+    if (nsi->state != NSIOD_STATE_DELETED && nsi->events_pending) {
+      int sd, evmask = EV_NONE;
+      POLLFD *pev;
+
+#if HAVE_PCAP
+      if (nsi->pcap)
+        sd = ((mspcap *)nsi->pcap)->pcap_desc;
+      else
+#endif
+        sd = nsi->sd;
+
+      pev = &pinfo->events[sd];
+
+      if (pev->revents & POLL_R_FLAGS)
+        evmask |= EV_READ;
+      if (pev->revents & POLL_W_FLAGS)
+        evmask |= EV_WRITE;
+      if (pev->revents & POLL_X_FLAGS)
+        evmask |= (EV_READ | EV_WRITE | EV_EXCEPT);
+
+      process_iod_events(nsp, nsi, evmask);
+    }
+
+    next = GH_LIST_ELEM_NEXT(current);
+    if (nsi->state == NSIOD_STATE_DELETED) {
+      gh_list_remove_elem(&nsp->active_iods, current);
+      gh_list_prepend(&nsp->free_iods, nsi);
+    }
+  }
+
+  /* iterate through timers */
+  for (current = GH_LIST_FIRST_ELEM(&nsp->timer_events);
+       current != NULL && GH_LIST_ELEM_PREV(current) != timer_last; current = next) {
+
+    msevent *nse = (msevent *)GH_LIST_ELEM_DATA(current);
+
+    process_event(nsp, &nsp->timer_events, nse, EV_NONE);
+
+    next = GH_LIST_ELEM_NEXT(current);
+    if (nse->event_done)
+      gh_list_remove_elem(&nsp->timer_events, current);
+  }
+}
+
+#endif /* HAVE_POLL */
+
