1
0
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:
dmiller
2024-10-30 19:02:09 +00:00
parent f1559fbc22
commit 0e3a51c992
3 changed files with 65 additions and 4 deletions

View File

@@ -2639,6 +2639,16 @@ static void processData(UltraScanInfo *USI) {
probe = *probeI;
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);
// give up completely after this long
expire_us = host->probeExpireTime(probe, to_us);

View File

@@ -557,6 +557,9 @@ public:
bool ping_scan_arp; /* ONLY includes arp ping scan */
bool ping_scan_nd; /* ONLY includes ND ping scan */
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. */
/* If ping_scan is true (unless ping_scan_arp is also true), this is the set

View File

@@ -71,6 +71,10 @@
#include <errno.h>
#ifdef WIN32
#include <mstcpip.h>
#endif
extern NmapOps o;
/* 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;
int newportstate = PORT_UNKNOWN;
int newhoststate = HOST_UNKNOWN;
reason_t current_reason = ER_NORESPONSE;
reason_t current_reason = ER_UNKNOWN;
UltraProbe *probe = *probeI;
struct sockaddr_storage local;
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));
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);
} else if (USI->ping_scan && newhoststate != HOST_UNKNOWN) {
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
bandwidth with the four-step close. Set the source address if needed. Bind to
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;
struct linger l;
struct sockaddr_storage ss;
@@ -382,6 +389,47 @@ static void init_socket(int sd) {
error("Problem setting socket SO_LINGER, errno: %d", socket_errno());
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, &params, 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) {
o.SourceSockAddr(&ss, &sslen);
if (::bind(sd, (struct sockaddr*)&ss, sslen) != 0) {
@@ -426,7 +474,7 @@ UltraProbe *sendConnectScanProbe(UltraScanInfo *USI, HostScanStats *hss,
CP->sd = CSI->getSocket();
assert(CP->sd > 0);
unblock_socket(CP->sd);
init_socket(CP->sd);
init_socket(CP->sd, hss, USI);
set_ttl(CP->sd, o.ttl);
if (o.ipoptionslen)
set_ipoptions(CP->sd, o.ipoptions, o.ipoptionslen);