--- nmap-6.49BETA4-orig/nmap.cc 2015-06-23 16:46:12.000000000 -0500 +++ nmap-6.49BETA4/nmap.cc 2015-09-09 15:44:08.179610848 -0500 @@ -1901,7 +1901,11 @@ ) || o.listscan) { /* We're done with the hosts */ if (currenths->flags & HOST_UP || (o.verbose && !o.openOnly())) { - xml_start_tag("host"); + xml_open_start_tag("host"); + if (!currenths->tag().empty()) { + xml_attribute("tag", "%s", currenths->tag().c_str()); + } + xml_close_start_tag(); write_host_header(currenths); printmacinfo(currenths); // if (currenths->flags & HOST_UP) @@ -1926,7 +1930,11 @@ connected to */ if (!(currenths->flags & HOST_UP)) { if (o.verbose && (!o.openOnly() || currenths->ports.hasOpenPorts())) { - xml_start_tag("host"); + xml_open_start_tag("host"); + if (!currenths->tag().empty()) { + xml_attribute("tag", "%s", currenths->tag().c_str()); + } + xml_close_start_tag(); write_host_header(currenths); xml_end_tag(); xml_newline(); @@ -2067,6 +2075,9 @@ /* Now I can do the output and such for each host */ if (currenths->timedOut(NULL)) { xml_open_start_tag("host"); + if (!currenths->tag().empty()) { + xml_attribute("tag", "%s", currenths->tag().c_str()); + } xml_attribute("starttime", "%lu", (unsigned long) currenths->StartTime()); xml_attribute("endtime", "%lu", (unsigned long) currenths->EndTime()); xml_close_start_tag(); @@ -2083,6 +2094,9 @@ continue; xml_open_start_tag("host"); + if (!currenths->tag().empty()) { + xml_attribute("tag", "%s", currenths->tag().c_str()); + } xml_attribute("starttime", "%lu", (unsigned long) currenths->StartTime()); xml_attribute("endtime", "%lu", (unsigned long) currenths->EndTime()); xml_close_start_tag(); --- nmap-6.49BETA4-orig/TargetGroup.cc 2015-06-16 08:59:33.000000000 -0500 +++ nmap-6.49BETA4/TargetGroup.cc 2015-09-09 15:49:12.323623089 -0500 @@ -264,12 +264,25 @@ /* 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 - parameter is AF_INET or AF_INET6. Returns NULL in case of error. */ -NetBlock *NetBlock::parse_expr(const char *target_expr, int af) { + parameter is AF_INET or AF_INET6. Returns NULL in case of error. + The expression may have a suffix such as 192.168.0.1^mytag which + will not be considered part of the address or hostname and can be + included in [xml] output to tie it back to the expression given for + input. */ +NetBlock *NetBlock::parse_expr(const char *target_expr_, int af) { + char* target_expr = strdup(target_expr_); NetBlock *netblock; char *hostexp; int bits; + /* parse off a ^tag suffix, if it exists */ + std::string tag; + size_t tagpos = std::string(target_expr).rfind('^'); + if (tagpos != std::string::npos) { + tag.assign(target_expr+tagpos+1); + target_expr[tagpos] = 0; + } + hostexp = split_netmask(target_expr, &bits); if (hostexp == NULL) { error("Unable to split netmask from target expression: \"%s\"", target_expr); @@ -286,10 +299,13 @@ goto bail; netblock->apply_netmask(bits); + free(target_expr); free(hostexp); + netblock->tag = tag; return netblock; bail: + free(target_expr); free(hostexp); return NULL; } @@ -683,6 +699,7 @@ if (netblock == NULL) return NULL; + netblock->tag = this->tag; netblock->hostname = this->hostname; netblock->resolvedaddrs = resolvedaddrs; netblock->apply_netmask(this->bits); --- nmap-6.49BETA4-orig/TargetGroup.h 2015-06-16 08:59:33.000000000 -0500 +++ nmap-6.49BETA4/TargetGroup.h 2015-09-09 14:44:50.295467644 -0500 @@ -147,6 +147,7 @@ class NetBlock { public: virtual ~NetBlock() {} + std::string tag; std::string hostname; std::list resolvedaddrs; --- nmap-6.49BETA4-orig/Target.h 2015-06-16 08:59:33.000000000 -0500 +++ nmap-6.49BETA4/Target.h 2015-09-09 14:43:40.175464821 -0500 @@ -210,6 +210,8 @@ const char *targetipstr() const { return targetipstring; } /* The IPv4 or IPv6 literal string for the source address */ const char *sourceipstr() const { return sourceipstring; } + const std::string& tag() const { return the_tag; } + void setTag(const std::string& t) { the_tag = t; } /* Give the name from the last setHostName() call, which should be the name obtained from reverse-resolution (PTR query) of the IP (v4 or v6). If the name has not been set, or was set to NULL, an empty @@ -313,6 +315,7 @@ int weird_responses; /* echo responses from other addresses, Ie a network broadcast address */ unsigned int flags; /* HOST_UNKNOWN, HOST_UP, or HOST_DOWN. */ struct timeout_info to; + std::string the_tag; 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 --- nmap-6.49BETA4-orig/targets.cc 2015-07-05 17:06:09.000000000 -0500 +++ nmap-6.49BETA4/targets.cc 2015-09-09 15:44:55.011612733 -0500 @@ -513,6 +513,8 @@ t = new Target(); + t->setTag(hs->current_group.netblock->tag); + t->setTargetSockAddr(ss, sslen); /* Special handling for the resolved address (for example whatever