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;
|
||||
|
||||
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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ¶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) {
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user