From 5d8a4cc56bdeca0e98ba709a83c779b9a72b2fc7 Mon Sep 17 00:00:00 2001 From: I-am-Krish Date: Mon, 24 Aug 2026 17:22:34 +0530 Subject: [PATCH] Fix missing XML hostnames when --unique is used (#3409) When using the --unique flag, duplicate IPs are skipped to avoid redundant scanning. However, if a user provided multiple aliases for the same IP (e.g. '127.0.0.1 localhost'), the aliases were silently discarded when skipped, resulting in missing '' tags in the XML output. This commit resolves the issue by extending the Target class to support storing multiple aliases. During host generation (HostGroupState::get_next_host), if a named host is skipped due to the --unique flag, its name is now looked up in the current hostbatch and appended to the existing Target's aliases. Finally, output.cc was updated to iterate over and print all collected aliases. --- Target.cc | 10 ++++++++++ Target.h | 7 +++++++ output.cc | 8 ++++++++ targets.cc | 15 +++++++++++++++ targets.h | 1 + 5 files changed, 41 insertions(+) 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;