|
|
@@ -1,5 +1,6 @@ |
|
|
#include "tcpscanner.h" |
|
|
#include <boost/lexical_cast.hpp> |
|
|
#include <iostream> |
|
|
|
|
|
using namespace std; |
|
|
using namespace boost; |
|
@@ -111,12 +112,23 @@ void TcpScanner::initSocket(Service* service) |
|
|
u_long mode = 1; |
|
|
ioctlsocket(sock, FIONBIO, &mode); |
|
|
|
|
|
// allocate file descriptor set |
|
|
// set up the OS's choice of signaling for non-blocking sockets |
|
|
|
|
|
#if Windows |
|
|
|
|
|
WSAEVENT evt = WSACreateEvent(); |
|
|
WSAEventSelect(sock, evt, FD_WRITE); |
|
|
WSAResetEvent(evt); |
|
|
data->event = evt; |
|
|
|
|
|
#elif Linux |
|
|
|
|
|
data->fdset = new fd_set(); |
|
|
FD_ZERO(data->fdset); |
|
|
FD_SET(sock, data->fdset); |
|
|
|
|
|
#endif |
|
|
|
|
|
// start non-blocking connection process |
|
|
|
|
|
connect(sock, reinterpret_cast<struct sockaddr*>(info->ai_addr), info->ai_addrlen); |
|
@@ -129,49 +141,57 @@ void TcpScanner::pollSocket(Service* service, bool last) |
|
|
return; |
|
|
} |
|
|
|
|
|
TIMEVAL tv = { 0, 0 }; |
|
|
auto data = reinterpret_cast<TcpScanData*>(service->data); |
|
|
|
|
|
// check if socket is writable, which basically means the connection was successful |
|
|
#if Windows |
|
|
|
|
|
// for some reason, Linux requires the first parameter to be counterintuitively socket+1, while Windows doesn't |
|
|
// time spent searching for this error: ~1.5 hours |
|
|
// check if the event was signalled |
|
|
|
|
|
select( |
|
|
data->socket |
|
|
#if Linux |
|
|
+ 1 |
|
|
#endif |
|
|
, nullptr, data->fdset, nullptr, &tv |
|
|
); |
|
|
auto sigr = WSAWaitForMultipleEvents(1, &data->event, false, 0, false); |
|
|
auto serr = WSAGetLastError(); |
|
|
|
|
|
// check if the writable flag is set |
|
|
// the return value 258 is not documented in MSDN, however this |
|
|
// is what seems to be returned in case of errors |
|
|
|
|
|
auto isOpen = FD_ISSET(data->socket, data->fdset); |
|
|
if (sigr == 258 && serr != WSAEWOULDBLOCK) |
|
|
{ |
|
|
service->alive = false; |
|
|
service->reason = AR_IcmpUnreachable; |
|
|
} |
|
|
else if (sigr == 0) |
|
|
{ |
|
|
service->alive = true; |
|
|
} |
|
|
|
|
|
#if Linux |
|
|
if (isOpen) |
|
|
#elif Linux |
|
|
|
|
|
// check if socket is writable |
|
|
|
|
|
TIMEVAL tv = { 0, 0 }; |
|
|
select(data->socket + 1, nullptr, data->fdset, nullptr, &tv); |
|
|
|
|
|
if (FD_ISSET(data->socket, data->fdset)) |
|
|
{ |
|
|
// yet again Linux decided to troll me. all select() requests will become "writable", and you have |
|
|
// to check if there was an error or not, to actually determine if the connect() was successful |
|
|
// since it seems writability bit will be set on connection refused errors, |
|
|
// check if this is a legit instance of writable socket or an error |
|
|
|
|
|
int serr; |
|
|
socklen_t slen = sizeof(serr); |
|
|
getsockopt(data->socket, SOL_SOCKET, SO_ERROR, &serr, &slen); |
|
|
isOpen = serr == 0; |
|
|
|
|
|
service->alive = serr == 0; |
|
|
|
|
|
if (serr == ECONNREFUSED) |
|
|
{ |
|
|
service->reason = AR_IcmpUnreachable; |
|
|
} |
|
|
} |
|
|
#endif |
|
|
|
|
|
service->alive = isOpen == 1; |
|
|
#endif |
|
|
|
|
|
// mark service accordingly |
|
|
|
|
|
if (isOpen) |
|
|
if (service->alive) |
|
|
{ |
|
|
service->reason = AR_InProgress2; |
|
|
readBanner(service, last); |
|
@@ -185,8 +205,10 @@ void TcpScanner::pollSocket(Service* service, bool last) |
|
|
} |
|
|
else if (service->reason == AR_InProgress) |
|
|
{ |
|
|
#if Linux |
|
|
FD_ZERO(data->fdset); |
|
|
FD_SET(data->socket, data->fdset); |
|
|
#endif |
|
|
return; |
|
|
} |
|
|
} |
|
@@ -197,7 +219,12 @@ void TcpScanner::pollSocket(Service* service, bool last) |
|
|
|
|
|
closesocket(data->socket); |
|
|
|
|
|
#if Windows |
|
|
WSACloseEvent(data->event); |
|
|
#elif Linux |
|
|
delete data->fdset; |
|
|
#endif |
|
|
|
|
|
delete data; |
|
|
} |
|
|
|
|
@@ -245,7 +272,12 @@ void TcpScanner::readBanner(Service* service, bool last) |
|
|
shutdown(data->socket, SD_BOTH); |
|
|
closesocket(data->socket); |
|
|
|
|
|
#if Windows |
|
|
WSACloseEvent(data->event); |
|
|
#elif Linux |
|
|
delete data->fdset; |
|
|
#endif |
|
|
|
|
|
delete data; |
|
|
} |
|
|
|
|
|