From 9baacdf9e3817c1ab52ddf5bd0e62b03f1cbf1df Mon Sep 17 00:00:00 2001 From: henri Date: Thu, 5 Jul 2012 14:35:51 +0000 Subject: [PATCH] [NSOCK] Fixed an epoll-engine-specific bug. The engine didn't recognized FDs that were internally closed and replaced by other ones. This happened during reconnect attempts. -- When reconnecting with SSL_OP_NO_SSLv2 (nsock_core.c:472), the libary closes the fd of the current IOD, and replaces it by a new one. The man page for epoll_ctl states that a close() on a fd makes it removed from any epoll set it was in. Therefore, if epoll_ctl(EPOLL_CTL_MOD, ...) returns ENOENT, we retry with EPOLL_CTL_ADD. --- CHANGELOG | 4 ++++ nsock/src/engine_epoll.c | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index a3f94996e..eea9c1568 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,8 @@ # Nmap Changelog ($Id$); -*-text-*- +o [NSOCK] Fixed an epoll-engine-specific bug. The engine didn't recognized FDs + that were internally closed and replaced by other ones. This happened during + reconnect attempts. [Henri Doreau] + o Added support for log type bitmasks in log_vwrite(). Also replaced a fatal() statement by an assert(0) to get rid of a possible infinite call loop when passed an invalid log type. [Henri Doreau] diff --git a/nsock/src/engine_epoll.c b/nsock/src/engine_epoll.c index 4aad53bb6..d8b2f3bdf 100644 --- a/nsock/src/engine_epoll.c +++ b/nsock/src/engine_epoll.c @@ -230,7 +230,16 @@ int epoll_iod_modify(mspool *nsp, msiod *iod, int ev_set, int ev_clr) { epev.events |= EPOLL_X_FLAGS; sd = nsi_getsd(iod); - epoll_ctl(einfo->epfd, EPOLL_CTL_MOD, sd, &epev); + if (epoll_ctl(einfo->epfd, EPOLL_CTL_MOD, sd, &epev) < 0) { + if (errno == ENOENT) { + /* This IOD is registered but its associated fd is not in the epoll set. + * It was probably closed and another one was open (e.g.: reconnect operation). + * We therefore want to add the new one. */ + epoll_ctl(einfo->epfd, EPOLL_CTL_ADD, sd, &epev); + } else { + fatal("Unable to update events for IOD #%lu: %s", iod->id, strerror(errno)); + } + } return 1; }