diff --git a/Target.cc b/Target.cc index 7195a4f52..c73bac9d7 100644 --- a/Target.cc +++ b/Target.cc @@ -356,6 +356,16 @@ void Target::setTargetName(const char *name) { } } +void Target::addTargetNameAlias(const char *name) { + if (name) + target_aliases.push_back(std::string(name)); +} + +const std::vector &Target::getTargetNameAliases() const { + return target_aliases; +} + + /* Generates a printable string consisting of the host's IP address and hostname (if available). Eg "www.insecure.org (64.71.184.53)" or "fe80::202:e3ff:fe14:1102". The name is diff --git a/Target.h b/Target.h index e73aea32e..730dabc1b 100644 --- a/Target.h +++ b/Target.h @@ -184,6 +184,11 @@ class Target { order */ void setTargetName(const char *name); + /* Add an additional user-supplied name that resolved to the same IP as this + target (recorded when --unique suppresses duplicate scanning). */ + void addTargetNameAlias(const char *name); + /* Returns the list of additional user-supplied names for this target. */ + const std::vector &getTargetNameAliases() const; /* If the host is directly connected on a network, set and retrieve that information here. directlyConnected() will abort if it hasn't @@ -262,6 +267,8 @@ class Target { struct timeout_info to; char *hostname; // Null if unable to resolve or unset char * targetname; // The name of the target host given on the command line if it is a named host + std::vector target_aliases; /* Additional user-supplied names that resolved to this + same IP, collected when --unique suppresses duplicate scanning. */ struct probespec traceroute_probespec; std::list traceroute_hops; diff --git a/output.cc b/output.cc index 995949f92..003306297 100644 --- a/output.cc +++ b/output.cc @@ -1281,6 +1281,14 @@ static void write_xml_initial_hostinfo(const Target *currenths, xml_close_empty_tag(); xml_newline(); } + /* Print additional names collected when --unique suppressed duplicate scanning. */ + for (const std::string &alias : currenths->getTargetNameAliases()) { + xml_open_start_tag("hostname"); + xml_attribute("name", "%s", alias.c_str()); + xml_attribute("type", "user"); + xml_close_empty_tag(); + xml_newline(); + } if (*currenths->HostName()) { xml_open_start_tag("hostname"); xml_attribute("name", "%s", currenths->HostName()); diff --git a/targets.cc b/targets.cc index 483d43b96..a7cfa6e6b 100644 --- a/targets.cc +++ b/targets.cc @@ -467,6 +467,21 @@ bool HostGroupState::get_next_host(struct sockaddr_storage *ss, size_t *sslen, s current_group.reject_last_host(); break; } + /* This IP is already in the exclude list (a --unique duplicate). + At this point *ss holds the excluded IP. If it came from a named + host, attach that name as an alias on the existing Target in the + current batch so it appears in XML output. */ + if (o.unique && current_group.get_namedhost()) { + const char *skipped_name = current_group.get_resolved_name(); + if (skipped_name) { + for (int i = 0; i < current_batch_sz; i++) { + if (sockaddr_storage_cmp(hostbatch[i]->TargetSockAddr(), ss) == 0) { + hostbatch[i]->addTargetNameAlias(skipped_name); + break; + } + } + } + } } while (true); return true; diff --git a/targets.h b/targets.h index 1e001ca5f..9f3cd4f40 100644 --- a/targets.h +++ b/targets.h @@ -66,6 +66,7 @@ #include "TargetGroup.h" #include +#include #include class Target;