diff --git a/Target.h b/Target.h index d4c98d0411..ee1e5f2d20 100644 --- a/Target.h +++ b/Target.h @@ -283,6 +283,11 @@ class Target { struct probespec traceroute_probespec; std::list traceroute_hops; + /* If the address for this target came from a DNS lookup, the list of + resultant addresses (sometimes there are more than one). The address + actually used is always the first element in this list. */ + std::list resolved_addrs; + #ifndef NOLUA ScriptResults scriptResults; #endif diff --git a/TargetGroup.cc b/TargetGroup.cc index b98ea0bdee..3547d24aed 100644 --- a/TargetGroup.cc +++ b/TargetGroup.cc @@ -167,6 +167,8 @@ int TargetGroup::parse_expr(const char * const target_expr, int af) { ipsleft = 0; + resolvedaddrs.clear(); + if (af == AF_INET) { if (strchr(hostexp, ':')) @@ -206,14 +208,24 @@ int TargetGroup::parse_expr(const char * const target_expr, int af) { break; } if (netmask != 32 || namedhost) { + struct in_addr addr; + targets_type = IPV4_NETMASK; - if (!inet_pton(AF_INET, target_net, &(resolvedaddr))) { + if (!inet_pton(AF_INET, target_net, &(addr))) { if ((target = gethostbyname(target_net))) { int count=0; - memcpy(&(resolvedaddr), target->h_addr_list[0], sizeof(resolvedaddr)); + memcpy(&(addr), target->h_addr_list[0], sizeof(addr)); - while (target->h_addr_list[count]) count++; + while (target->h_addr_list[count]) { + struct sockaddr_storage ss; + struct sockaddr_in *sin = (struct sockaddr_in *) &ss; + + sin->sin_family = AF_INET; + sin->sin_addr = addr; + resolvedaddrs.push_back(ss); + count++; + } if (count > 1) error("Warning: Hostname %s resolves to %d IPs. Using %s.", target_net, count, inet_ntoa(*((struct in_addr *)target->h_addr_list[0]))); @@ -224,7 +236,7 @@ int TargetGroup::parse_expr(const char * const target_expr, int af) { } } if (netmask) { - unsigned long longtmp = ntohl(resolvedaddr.s_addr); + unsigned long longtmp = ntohl(addr.s_addr); startaddr.s_addr = longtmp & (unsigned long) (0 - (1<<(32 - netmask))); endaddr.s_addr = longtmp | (unsigned long) ((1<<(32 - netmask)) - 1); } else { @@ -516,13 +528,21 @@ int TargetGroup::return_last_host() { netmask. */ bool TargetGroup::is_resolved_address(const struct sockaddr_storage *ss) { - const struct sockaddr_in *sin; + const struct sockaddr_in *sin, *sin_resolved; + struct sockaddr_storage resolvedaddr; - if (targets_type != IPV4_NETMASK || ss->ss_family != AF_INET) + if (targets_type != IPV4_NETMASK || ss->ss_family != AF_INET + || resolvedaddrs.empty()) { + return false; + } + resolvedaddr = *resolvedaddrs.begin(); + if (resolvedaddr.ss_family != AF_INET) return false; + sin = (struct sockaddr_in *) ss; + sin_resolved = (struct sockaddr_in *) &resolvedaddr; - return sin->sin_addr.s_addr == resolvedaddr.s_addr; + return sin->sin_addr.s_addr == sin_resolved->sin_addr.s_addr; } /* Return a string of the name or address that was resolved for this group. */ @@ -531,6 +551,13 @@ const char *TargetGroup::get_resolved_name(void) return resolvedname.c_str(); } +/* Return the list of addresses that the name for this group resolved to, if + it came from a name resolution. */ +const std::list &TargetGroup::get_resolved_addrs(void) +{ + return resolvedaddrs; +} + /* Lookahead is the number of hosts that can be checked (such as ping scanned) in advance. Randomize causes each group of up to lookahead hosts to be internally shuffled around. diff --git a/TargetGroup.h b/TargetGroup.h index 36f8fe036e..e7c3d6ab2f 100644 --- a/TargetGroup.h +++ b/TargetGroup.h @@ -95,6 +95,7 @@ #ifndef TARGETGROUP_H #define TARGETGROUP_H +#include #include #include "nmap.h" @@ -129,6 +130,9 @@ class TargetGroup { bool is_resolved_address(const struct sockaddr_storage *ss); /* Return a string of the name or address that was resolved for this group. */ const char *get_resolved_name(void); + /* Return the list of addresses that the name for this group resolved to, if + it came from a name resolution. */ + const std::list &get_resolved_addrs(void); /* return the target type */ char get_targets_type() {return targets_type;}; /* get the netmask */ @@ -145,11 +149,12 @@ class TargetGroup { struct sockaddr_in6 ip6; #endif + std::list resolvedaddrs; + /* These are used for the '/mask' style of specifying target net (IPV4_NETMASK) */ u32 netmask; std::string resolvedname; - struct in_addr resolvedaddr; struct in_addr startaddr; struct in_addr currentaddr; struct in_addr endaddr; diff --git a/output.cc b/output.cc index e6d22dbb61..5a919d75e2 100644 --- a/output.cc +++ b/output.cc @@ -1427,6 +1427,12 @@ void write_host_header(Target *currenths) { if ((currenths->flags & HOST_UP) || o.verbose || o.resolve_all) log_write(LOG_PLAIN, "Nmap scan report for %s\n", currenths->NameIP()); write_host_status(currenths, o.resolve_all); + if (currenths->TargetName() != NULL + && currenths->resolved_addrs.size() > 1) { + log_write(LOG_PLAIN, "Hostname %s resolves to %u IPs. Only scanned %s\n", + currenths->TargetName(), currenths->resolved_addrs.size(), + currenths->targetipstr()); + } /* Print reverse DNS if it differs. */ if (currenths->TargetName() != NULL && currenths->HostName() != NULL && currenths->HostName()[0] != '\0' diff --git a/targets.cc b/targets.cc index 6c8e6a18c5..b5efacbdea 100644 --- a/targets.cc +++ b/targets.cc @@ -463,6 +463,7 @@ do { if (hs->current_expression.is_resolved_address(&ss)) { if (hs->current_expression.get_namedhost()) hs->hostbatch[hidx]->setTargetName(hs->current_expression.get_resolved_name()); + hs->hostbatch[hidx]->resolved_addrs = hs->current_expression.get_resolved_addrs(); } /* We figure out the source IP/device IFF