mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Set timeouts for Windows connect scan. Fixes #2113
This commit is contained in:
@@ -2639,6 +2639,16 @@ static void processData(UltraScanInfo *USI) {
|
|||||||
probe = *probeI;
|
probe = *probeI;
|
||||||
|
|
||||||
unsigned long to_us = host->probeTimeout();
|
unsigned long to_us = host->probeTimeout();
|
||||||
|
#ifdef WIN32
|
||||||
|
if (USI->scantype == CONNECT_SCAN || USI->ptech.connecttcpscan) {
|
||||||
|
// Have to adjust to_us up because of TCP_MAXRT granularity
|
||||||
|
if (USI->has_tcp_maxrtms) {
|
||||||
|
to_us += (1000 - to_us % 1000);
|
||||||
|
} else {
|
||||||
|
to_us += (1000000 - to_us % 1000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
long probe_age_us = TIMEVAL_SUBTRACT(USI->now, probe->sent);
|
long probe_age_us = TIMEVAL_SUBTRACT(USI->now, probe->sent);
|
||||||
// give up completely after this long
|
// give up completely after this long
|
||||||
expire_us = host->probeExpireTime(probe, to_us);
|
expire_us = host->probeExpireTime(probe, to_us);
|
||||||
|
|||||||
@@ -557,6 +557,9 @@ public:
|
|||||||
bool ping_scan_arp; /* ONLY includes arp ping scan */
|
bool ping_scan_arp; /* ONLY includes arp ping scan */
|
||||||
bool ping_scan_nd; /* ONLY includes ND ping scan */
|
bool ping_scan_nd; /* ONLY includes ND ping scan */
|
||||||
bool noresp_open_scan; /* Whether no response means a port is open */
|
bool noresp_open_scan; /* Whether no response means a port is open */
|
||||||
|
#ifdef WIN32
|
||||||
|
bool has_tcp_maxrtms; /* Whether TCP_MAXRTMS socket option is available */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* massping state. */
|
/* massping state. */
|
||||||
/* If ping_scan is true (unless ping_scan_arp is also true), this is the set
|
/* If ping_scan is true (unless ping_scan_arp is also true), this is the set
|
||||||
|
|||||||
@@ -71,6 +71,10 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <mstcpip.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
extern NmapOps o;
|
extern NmapOps o;
|
||||||
|
|
||||||
/* Sets this UltraProbe as type UP_CONNECT, preparing to connect to given
|
/* Sets this UltraProbe as type UP_CONNECT, preparing to connect to given
|
||||||
@@ -215,7 +219,7 @@ static void handleConnectResult(UltraScanInfo *USI, HostScanStats *hss,
|
|||||||
bool adjust_timing = true;
|
bool adjust_timing = true;
|
||||||
int newportstate = PORT_UNKNOWN;
|
int newportstate = PORT_UNKNOWN;
|
||||||
int newhoststate = HOST_UNKNOWN;
|
int newhoststate = HOST_UNKNOWN;
|
||||||
reason_t current_reason = ER_NORESPONSE;
|
reason_t current_reason = ER_UNKNOWN;
|
||||||
UltraProbe *probe = *probeI;
|
UltraProbe *probe = *probeI;
|
||||||
struct sockaddr_storage local;
|
struct sockaddr_storage local;
|
||||||
socklen_t local_len = sizeof(struct sockaddr_storage);
|
socklen_t local_len = sizeof(struct sockaddr_storage);
|
||||||
@@ -311,7 +315,10 @@ static void handleConnectResult(UltraScanInfo *USI, HostScanStats *hss,
|
|||||||
error("Strange read error from %s (%d - '%s')", hss->target->targetipstr(), connect_errno, strerror(connect_errno));
|
error("Strange read error from %s (%d - '%s')", hss->target->targetipstr(), connect_errno, strerror(connect_errno));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (probe->isPing() && newhoststate != HOST_UNKNOWN ) {
|
if (current_reason == ER_NORESPONSE) {
|
||||||
|
hss->markProbeTimedout(probeI);
|
||||||
|
}
|
||||||
|
else if (probe->isPing() && newhoststate != HOST_UNKNOWN ) {
|
||||||
ultrascan_ping_update(USI, hss, probeI, &USI->now, adjust_timing);
|
ultrascan_ping_update(USI, hss, probeI, &USI->now, adjust_timing);
|
||||||
} else if (USI->ping_scan && newhoststate != HOST_UNKNOWN) {
|
} else if (USI->ping_scan && newhoststate != HOST_UNKNOWN) {
|
||||||
ultrascan_host_probe_update(USI, hss, probeI, newhoststate, &USI->now, adjust_timing);
|
ultrascan_host_probe_update(USI, hss, probeI, newhoststate, &USI->now, adjust_timing);
|
||||||
@@ -369,7 +376,7 @@ static void handleConnectResult(UltraScanInfo *USI, HostScanStats *hss,
|
|||||||
/* Set the socket lingering so we will RST connections instead of wasting
|
/* Set the socket lingering so we will RST connections instead of wasting
|
||||||
bandwidth with the four-step close. Set the source address if needed. Bind to
|
bandwidth with the four-step close. Set the source address if needed. Bind to
|
||||||
a specific interface if needed. */
|
a specific interface if needed. */
|
||||||
static void init_socket(int sd) {
|
static void init_socket(int sd, const HostScanStats *hss, UltraScanInfo *USI) {
|
||||||
static int bind_failed = 0;
|
static int bind_failed = 0;
|
||||||
struct linger l;
|
struct linger l;
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
@@ -382,6 +389,47 @@ static void init_socket(int sd) {
|
|||||||
error("Problem setting socket SO_LINGER, errno: %d", socket_errno());
|
error("Problem setting socket SO_LINGER, errno: %d", socket_errno());
|
||||||
perror("setsockopt");
|
perror("setsockopt");
|
||||||
}
|
}
|
||||||
|
#ifdef WIN32
|
||||||
|
DWORD dwVal;
|
||||||
|
unsigned long to_us = hss->probeTimeout();
|
||||||
|
#ifdef TCP_FAIL_CONNECT_ON_ICMP_ERROR
|
||||||
|
// return WSAEHOSTUNREACH on ICMP error. Default is to ignore!
|
||||||
|
dwVal = 1;
|
||||||
|
if (setsockopt(sd, IPPROTO_TCP, TCP_FAIL_CONNECT_ON_ICMP_ERROR, (const char *) &dwVal, sizeof(dwVal)) != 0) {
|
||||||
|
error("Problem setting socket TCP_FAIL_CONNECT_ON_ICMP_ERROR, errno: %d", socket_errno());
|
||||||
|
perror("setsockopt");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int err, opt;
|
||||||
|
do {
|
||||||
|
err = ERROR_SUCCESS;
|
||||||
|
if (USI->has_tcp_maxrtms) {
|
||||||
|
opt = TCP_MAXRTMS;
|
||||||
|
dwVal = to_us / 1000; // connect timeout in milliseconds
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
opt = TCP_MAXRT;
|
||||||
|
dwVal = to_us / 1000000; // connect timeout in seconds
|
||||||
|
}
|
||||||
|
dwVal = MAX(dwVal, 1);
|
||||||
|
if (setsockopt(sd, IPPROTO_TCP, opt, (const char*)&dwVal, sizeof(dwVal)) != 0) {
|
||||||
|
err = socket_errno();
|
||||||
|
error("Problem setting socket TCP_MAXRT (%d), errno: %d", opt, err);
|
||||||
|
perror("setsockopt");
|
||||||
|
USI->has_tcp_maxrtms = false;
|
||||||
|
}
|
||||||
|
} while (err == WSAENOPROTOOPT && opt == TCP_MAXRTMS);
|
||||||
|
|
||||||
|
dwVal = 0;
|
||||||
|
TCP_INITIAL_RTO_PARAMETERS params = { 1000 /* ms RTT */,
|
||||||
|
TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS };
|
||||||
|
if (WSAIoctl(sd, SIO_TCP_INITIAL_RTO, ¶ms, sizeof(params), NULL, 0, &dwVal, NULL, NULL)) {
|
||||||
|
error("Problem setting SIO_TCP_INITIAL_RTO, errno: %d", socket_errno());
|
||||||
|
perror("WSAIoctl");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (o.spoofsource && !bind_failed) {
|
if (o.spoofsource && !bind_failed) {
|
||||||
o.SourceSockAddr(&ss, &sslen);
|
o.SourceSockAddr(&ss, &sslen);
|
||||||
if (::bind(sd, (struct sockaddr*)&ss, sslen) != 0) {
|
if (::bind(sd, (struct sockaddr*)&ss, sslen) != 0) {
|
||||||
@@ -426,7 +474,7 @@ UltraProbe *sendConnectScanProbe(UltraScanInfo *USI, HostScanStats *hss,
|
|||||||
CP->sd = CSI->getSocket();
|
CP->sd = CSI->getSocket();
|
||||||
assert(CP->sd > 0);
|
assert(CP->sd > 0);
|
||||||
unblock_socket(CP->sd);
|
unblock_socket(CP->sd);
|
||||||
init_socket(CP->sd);
|
init_socket(CP->sd, hss, USI);
|
||||||
set_ttl(CP->sd, o.ttl);
|
set_ttl(CP->sd, o.ttl);
|
||||||
if (o.ipoptionslen)
|
if (o.ipoptionslen)
|
||||||
set_ipoptions(CP->sd, o.ipoptions, o.ipoptionslen);
|
set_ipoptions(CP->sd, o.ipoptions, o.ipoptionslen);
|
||||||
|
|||||||
Reference in New Issue
Block a user