From 3ae9ba63be6d312bccd9865e61b8e1baaa6f0d61 Mon Sep 17 00:00:00 2001 From: david Date: Thu, 6 Sep 2012 18:17:27 +0000 Subject: [PATCH] Make sockets temporarily blocking in ncat_send and ncat_broadcast. It is possible to send so quickly that we start getting EAGAIN on sends. In listen mode, this means that some sends can get lost. This patch, adapted from one by Alex Weber, makes sockets blocking for the duration of the send. This is not as nice as retrying the send through an event mechanism, but should at least be correct. http://seclists.org/nmap-dev/2012/q3/670 Compare a similar patch in r13552, which applied to --exec mode. --- CHANGELOG | 4 ++++ ncat/ncat_core.c | 20 ++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d92f8fa92..dea75d81b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ # Nmap Changelog ($Id$); -*-text-*- +o [Ncat] Applied a blocking-socket workaround for a bug that could + prevent some sends from working in listen mode. The problem was + reported by Jonas Wielicki. [Alex Weber, David Fifield] + o Protocol scan (-sO) probes for TCP, UDP, and SCTP now go to ports 80, 40125, and 80 respectively, instead of being randomly generated or going to the same port as the source port. [David Fifield] diff --git a/ncat/ncat_core.c b/ncat/ncat_core.c index 8e0b55735..7a7407aae 100644 --- a/ncat/ncat_core.c +++ b/ncat/ncat_core.c @@ -291,6 +291,22 @@ int fdinfo_send(struct fdinfo *fdn, const char *buf, size_t size) return send(fdn->fd, buf, size, 0); } +/* If we are sending a large amount of data, we might momentarily run out of send + space and get an EAGAIN when we send. Temporarily convert a socket to + blocking more, do the send, and unblock it again. Assumes that the socket was + in nonblocking mode to begin with; it has the side effect of leaving the + socket nonblocking on return. */ +static int blocking_fdinfo_send(struct fdinfo *fdn, const char *buf, size_t size) +{ + int ret; + + block_socket(fdn->fd); + ret = fdinfo_send(fdn, buf, size); + unblock_socket(fdn->fd); + + return ret; +} + int ncat_send(struct fdinfo *fdn, const char *buf, size_t size) { int n; @@ -298,7 +314,7 @@ int ncat_send(struct fdinfo *fdn, const char *buf, size_t size) if (o.recvonly) return size; - n = fdinfo_send(fdn, buf, size); + n = blocking_fdinfo_send(fdn, buf, size); if (n <= 0) return n; @@ -323,7 +339,7 @@ int ncat_broadcast(fd_set *fds, const fd_list_t *fdlist, const char *msg, size_t continue; fdn = get_fdinfo(fdlist, i); - if (fdinfo_send(fdn, msg, size) <= 0) { + if (blocking_fdinfo_send(fdn, msg, size) <= 0) { if (o.debug > 1) logdebug("Error sending to fd %d: %s.\n", i, socket_strerror(socket_errno())); ret = -1;