mirror of
https://github.com/nmap/nmap.git
synced 2025-12-09 22:21:29 +00:00
Resolveall feature. Fixes #949
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
# Nmap Changelog ($Id$); -*-text-*-
|
# Nmap Changelog ($Id$); -*-text-*-
|
||||||
|
|
||||||
|
o Nmap can now resolve and scan all IP addresses of a host. Instead of using
|
||||||
|
the resolveall NSE script, append "*all" to a target hostname:
|
||||||
|
nmap example.com*all another.example.com*all/24
|
||||||
|
[Daniel Miller]
|
||||||
|
|
||||||
o [GH#957] Fix reporting of zlib and libssh2 versions in "nmap --version". We
|
o [GH#957] Fix reporting of zlib and libssh2 versions in "nmap --version". We
|
||||||
were always reporting the version number of the included source, even when a
|
were always reporting the version number of the included source, even when a
|
||||||
different version was linked. [Pavel Zhukov]
|
different version was linked. [Pavel Zhukov]
|
||||||
|
|||||||
@@ -163,6 +163,9 @@ public:
|
|||||||
std::string hostname;
|
std::string hostname;
|
||||||
std::list<struct sockaddr_storage> resolvedaddrs;
|
std::list<struct sockaddr_storage> resolvedaddrs;
|
||||||
std::list<struct sockaddr_storage> unscanned_addrs;
|
std::list<struct sockaddr_storage> unscanned_addrs;
|
||||||
|
std::list<struct sockaddr_storage>::const_iterator current_addr;
|
||||||
|
/* Scan all resolved addresses? */
|
||||||
|
bool resolveall;
|
||||||
|
|
||||||
/* Parses an expression such as 192.168.0.0/16, 10.1.0-5.1-254, or
|
/* Parses an expression such as 192.168.0.0/16, 10.1.0-5.1-254, or
|
||||||
fe80::202:e3ff:fe14:1102/112 and returns a newly allocated NetBlock. The af
|
fe80::202:e3ff:fe14:1102/112 and returns a newly allocated NetBlock. The af
|
||||||
@@ -214,7 +217,7 @@ private:
|
|||||||
|
|
||||||
class NetBlockHostname : public NetBlock {
|
class NetBlockHostname : public NetBlock {
|
||||||
public:
|
public:
|
||||||
NetBlockHostname(const char *hostname, int af);
|
NetBlockHostname(const char *hostname, int af, bool resolveall);
|
||||||
int af;
|
int af;
|
||||||
int bits;
|
int bits;
|
||||||
|
|
||||||
@@ -319,9 +322,32 @@ static int parse_ipv4_ranges(octet_bitvector octets[4], const char *spec) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *split_resolveall(const char *expr, bool *resolveall) {
|
||||||
|
const char *star;
|
||||||
|
|
||||||
|
star = strrchr(expr, '*');
|
||||||
|
if (star != NULL) {
|
||||||
|
if (strcmp(star + 1, "all") == 0) {
|
||||||
|
*resolveall = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Invalid syntax
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
star = expr + strlen(expr);
|
||||||
|
*resolveall = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mkstr(expr, star);
|
||||||
|
}
|
||||||
|
|
||||||
static NetBlock *parse_expr_without_netmask(const char *hostexp, int af) {
|
static NetBlock *parse_expr_without_netmask(const char *hostexp, int af) {
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
size_t sslen;
|
size_t sslen;
|
||||||
|
char *hostn;
|
||||||
|
bool resolveall = false;
|
||||||
|
|
||||||
if (af == AF_INET) {
|
if (af == AF_INET) {
|
||||||
NetBlockIPv4Ranges *netblock_ranges;
|
NetBlockIPv4Ranges *netblock_ranges;
|
||||||
@@ -346,7 +372,15 @@ static NetBlock *parse_expr_without_netmask(const char *hostexp, int af) {
|
|||||||
return netblock_ipv6;
|
return netblock_ipv6;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NetBlockHostname(hostexp, af);
|
hostn = split_resolveall(hostexp, &resolveall);
|
||||||
|
if (hostn == NULL) {
|
||||||
|
error("Invalid '*' in target expression: \"%s\"", hostexp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetBlockHostname *netblock_hostname = new NetBlockHostname(hostn, af, resolveall);
|
||||||
|
free(hostn);
|
||||||
|
return netblock_hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parses an expression such as 192.168.0.0/16, 10.1.0-5.1-254, or
|
/* Parses an expression such as 192.168.0.0/16, 10.1.0-5.1-254, or
|
||||||
@@ -439,12 +473,17 @@ bool NetBlockIPv4Ranges::next(struct sockaddr_storage *ss, size_t *sslen) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i >= 4) {
|
if (i >= 4) {
|
||||||
|
if (this->resolveall && current_addr != this->resolvedaddrs.end() && ++current_addr != this->resolvedaddrs.end()) {
|
||||||
|
this->set_addr((struct sockaddr_in *) &*current_addr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
/* We cycled all counters. Mark them invalid for the next call. */
|
/* We cycled all counters. Mark them invalid for the next call. */
|
||||||
this->counter[0] = 256;
|
this->counter[0] = 256;
|
||||||
this->counter[1] = 256;
|
this->counter[1] = 256;
|
||||||
this->counter[2] = 256;
|
this->counter[2] = 256;
|
||||||
this->counter[3] = 256;
|
this->counter[3] = 256;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -552,6 +591,7 @@ void NetBlockIPv4Ranges::set_addr(const struct sockaddr_in *addr) {
|
|||||||
|
|
||||||
assert(addr->sin_family == AF_INET);
|
assert(addr->sin_family == AF_INET);
|
||||||
ip = ntohl(addr->sin_addr.s_addr);
|
ip = ntohl(addr->sin_addr.s_addr);
|
||||||
|
memset(this->octets, 0, sizeof(this->octets));
|
||||||
BIT_SET(this->octets[0], (ip & 0xFF000000) >> 24);
|
BIT_SET(this->octets[0], (ip & 0xFF000000) >> 24);
|
||||||
BIT_SET(this->octets[1], (ip & 0x00FF0000) >> 16);
|
BIT_SET(this->octets[1], (ip & 0x00FF0000) >> 16);
|
||||||
BIT_SET(this->octets[2], (ip & 0x0000FF00) >> 8);
|
BIT_SET(this->octets[2], (ip & 0x0000FF00) >> 8);
|
||||||
@@ -593,8 +633,14 @@ static bool ipv6_equal(const struct in6_addr *a, const struct in6_addr *b) {
|
|||||||
bool NetBlockIPv6Netmask::next(struct sockaddr_storage *ss, size_t *sslen) {
|
bool NetBlockIPv6Netmask::next(struct sockaddr_storage *ss, size_t *sslen) {
|
||||||
struct sockaddr_in6 *sin6;
|
struct sockaddr_in6 *sin6;
|
||||||
|
|
||||||
if (this->exhausted)
|
if (this->exhausted){
|
||||||
|
if (this->resolveall && current_addr != this->resolvedaddrs.end() && ++current_addr != this->resolvedaddrs.end()) {
|
||||||
|
this->set_addr((struct sockaddr_in6 *) &*current_addr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memset(ss, 0, sizeof(*ss));
|
memset(ss, 0, sizeof(*ss));
|
||||||
sin6 = (struct sockaddr_in6 *) ss;
|
sin6 = (struct sockaddr_in6 *) ss;
|
||||||
@@ -717,7 +763,6 @@ NetBlock *NetBlockHostname::resolve() {
|
|||||||
std::list<struct sockaddr_storage> resolvedaddrs;
|
std::list<struct sockaddr_storage> resolvedaddrs;
|
||||||
std::list<struct sockaddr_storage> unscanned_addrs;
|
std::list<struct sockaddr_storage> unscanned_addrs;
|
||||||
NetBlock *netblock;
|
NetBlock *netblock;
|
||||||
const struct sockaddr_storage *sp = NULL;
|
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
size_t sslen;
|
size_t sslen;
|
||||||
|
|
||||||
@@ -725,9 +770,8 @@ NetBlock *NetBlockHostname::resolve() {
|
|||||||
for (addr = addrs; addr != NULL; addr = addr->ai_next) {
|
for (addr = addrs; addr != NULL; addr = addr->ai_next) {
|
||||||
if (addr->ai_addrlen < sizeof(ss)) {
|
if (addr->ai_addrlen < sizeof(ss)) {
|
||||||
memcpy(&ss, addr->ai_addr, addr->ai_addrlen);
|
memcpy(&ss, addr->ai_addr, addr->ai_addrlen);
|
||||||
if (sp == NULL && addr->ai_family == this->af) {
|
if ((resolveall || resolvedaddrs.empty()) && addr->ai_family == this->af) {
|
||||||
resolvedaddrs.push_back(ss);
|
resolvedaddrs.push_back(ss);
|
||||||
sp = &resolvedaddrs.back();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unscanned_addrs.push_back(ss);
|
unscanned_addrs.push_back(ss);
|
||||||
@@ -737,10 +781,10 @@ NetBlock *NetBlockHostname::resolve() {
|
|||||||
if (addrs != NULL)
|
if (addrs != NULL)
|
||||||
freeaddrinfo(addrs);
|
freeaddrinfo(addrs);
|
||||||
|
|
||||||
if (resolvedaddrs.empty() && unscanned_addrs.empty())
|
if (resolvedaddrs.empty()) {
|
||||||
|
if (unscanned_addrs.empty())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (sp == NULL) {
|
|
||||||
switch (this->af) {
|
switch (this->af) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
error("Warning: Hostname %s resolves, but not to any IPv4 address. Try scanning with -6", this->hostname.c_str());
|
error("Warning: Hostname %s resolves, but not to any IPv4 address. Try scanning with -6", this->hostname.c_str());
|
||||||
@@ -754,10 +798,10 @@ NetBlock *NetBlockHostname::resolve() {
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ss = *sp;
|
ss = resolvedaddrs.front();
|
||||||
sslen = sizeof(ss);
|
sslen = sizeof(ss);
|
||||||
|
|
||||||
if (!unscanned_addrs.empty() > 1 && o.verbose > 1) {
|
if (!unscanned_addrs.empty() && o.verbose > 1) {
|
||||||
error("Warning: Hostname %s resolves to %lu IPs. Using %s.", this->hostname.c_str(),
|
error("Warning: Hostname %s resolves to %lu IPs. Using %s.", this->hostname.c_str(),
|
||||||
(unsigned long) unscanned_addrs.size() + resolvedaddrs.size(), inet_ntop_ez(&ss, sslen));
|
(unsigned long) unscanned_addrs.size() + resolvedaddrs.size(), inet_ntop_ez(&ss, sslen));
|
||||||
}
|
}
|
||||||
@@ -783,15 +827,18 @@ NetBlock *NetBlockHostname::resolve() {
|
|||||||
netblock->hostname = this->hostname;
|
netblock->hostname = this->hostname;
|
||||||
netblock->resolvedaddrs = resolvedaddrs;
|
netblock->resolvedaddrs = resolvedaddrs;
|
||||||
netblock->unscanned_addrs = unscanned_addrs;
|
netblock->unscanned_addrs = unscanned_addrs;
|
||||||
|
netblock->resolveall = this->resolveall;
|
||||||
|
netblock->current_addr = netblock->resolvedaddrs.begin();
|
||||||
netblock->apply_netmask(this->bits);
|
netblock->apply_netmask(this->bits);
|
||||||
|
|
||||||
return netblock;
|
return netblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetBlockHostname::NetBlockHostname(const char *hostname, int af) {
|
NetBlockHostname::NetBlockHostname(const char *hostname, int af, bool resolveall) {
|
||||||
this->hostname = hostname;
|
this->hostname = hostname;
|
||||||
this->af = af;
|
this->af = af;
|
||||||
this->bits = -1;
|
this->bits = -1;
|
||||||
|
this->resolveall = resolveall;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetBlockHostname::next(struct sockaddr_storage *ss, size_t *sslen) {
|
bool NetBlockHostname::next(struct sockaddr_storage *ss, size_t *sslen) {
|
||||||
|
|||||||
Reference in New Issue
Block a user