diff -urNb old.nmap.rev/Makefile.in new.nmap.rev/Makefile.in
--- old.nmap.rev/Makefile.in Thu Nov 10 04:04:43 2005
+++ new.nmap.rev/Makefile.in Thu Nov 10 04:04:44 2005
@@ -46,11 +46,11 @@
TARGETNMAPFE=@TARGETNMAPFE@
INSTALLNMAPFE=@INSTALLNMAPFE@
-export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc @COMPAT_SRCS@
+export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc nmap_dns.cc @COMPAT_SRCS@
-OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o @COMPAT_OBJS@
+OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o nmap_dns.o @COMPAT_OBJS@
-export DEPS = nmap.h nmap_amigaos.h nmap_error.h targets.h idle_scan.h osscan.h output.h scan_engine.h timing.h tcpip.h utils.h global_structures.h charpool.h services.h protocols.h nmap_rpc.h portlist.h NmapOps.h TargetGroup.h Target.h FingerPrintResults.h service_scan.h NmapOutputTable.h MACLookup.h
+export DEPS = nmap.h nmap_amigaos.h nmap_error.h targets.h idle_scan.h osscan.h output.h scan_engine.h timing.h tcpip.h utils.h global_structures.h charpool.h services.h protocols.h nmap_rpc.h portlist.h NmapOps.h TargetGroup.h Target.h FingerPrintResults.h service_scan.h NmapOutputTable.h MACLookup.h nmap_dns.h
# %.o : %.cc -- nope this is a GNU extension
diff -urNb old.nmap.rev/NmapOps.cc new.nmap.rev/NmapOps.cc
--- old.nmap.rev/NmapOps.cc Thu Nov 10 04:04:42 2005
+++ new.nmap.rev/NmapOps.cc Thu Nov 10 04:04:43 2005
@@ -246,6 +246,7 @@
if (xsl_stylesheet) free(xsl_stylesheet);
xsl_stylesheet = strdup(tmpxsl);
spoof_mac_set = false;
+ mass_dns = true;
}
bool NmapOps::TCPScan() {
diff -urNb old.nmap.rev/NmapOps.h new.nmap.rev/NmapOps.h
--- old.nmap.rev/NmapOps.h Thu Nov 10 04:04:43 2005
+++ new.nmap.rev/NmapOps.h Thu Nov 10 04:04:44 2005
@@ -280,6 +280,7 @@
FILE *nmap_stdout; /* Nmap standard output */
int ttl; // Time to live
char *datadir;
+ bool mass_dns;
private:
int max_rtt_timeout;
int min_rtt_timeout;
diff -urNb old.nmap.rev/nmap.cc new.nmap.rev/nmap.cc
--- old.nmap.rev/nmap.cc Thu Nov 10 04:04:42 2005
+++ new.nmap.rev/nmap.cc Thu Nov 10 04:04:43 2005
@@ -107,6 +107,7 @@
#include "timing.h"
#include "NmapOps.h"
#include "MACLookup.h"
+#include "nmap_dns.h"
#ifdef WIN32
#include "winfix.h"
#endif
@@ -299,6 +300,7 @@
{"version_intensity", required_argument, 0, 0},
{"version_light", no_argument, 0, 0},
{"version_all", no_argument, 0, 0},
+ {"system_dns", no_argument, 0, 0},
{0, 0, 0, 0}
};
@@ -443,6 +445,8 @@
o.setXSLStyleSheet(optarg);
} else if (strcmp(long_options[option_index].name, "no_stylesheet") == 0) {
o.setXSLStyleSheet(NULL);
+ } else if (strcmp(long_options[option_index].name, "system_dns") == 0) {
+ o.mass_dns = false;
} else if (strcmp(long_options[option_index].name, "oN") == 0) {
normalfilename = optarg;
} else if (strcmp(long_options[option_index].name, "oG") == 0 ||
@@ -1083,26 +1087,9 @@
if (currenths->flags & HOST_UP && !o.listscan)
numhosts_up++;
- /* Lookup the IP */
- if (((currenths->flags & HOST_UP) || resolve_all) && !o.noresolve) {
- if (currenths->TargetSockAddr(&ss, &sslen) != 0)
- fatal("Failed to get target socket address.");
- if (getnameinfo((struct sockaddr *)&ss, sslen, hostname,
- sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) {
- currenths->setHostName(hostname);
- }
- }
-
if (o.pingscan || o.listscan) {
- /* We're done with the hosts */
- log_write(LOG_XML, "");
- write_host_status(currenths, resolve_all);
- printmacinfo(currenths);
- // if (currenths->flags & HOST_UP)
- // log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\n");
- log_write(LOG_XML, "\n");
- log_flush_all();
- delete currenths;
+ /* We're done with the hosts except for reverse DNS lookup */
+ Targets.push_back(currenths);
continue;
}
@@ -1154,8 +1141,31 @@
Targets.push_back(currenths);
}
- if (Targets.size() == 0)
+
+ if (Targets.size() > 0) {
+
+ // Do the parallel reverse DNS and print out the host info
+ // if this is a ping/list scan
+ if (!o.noresolve) nmap_mass_rdns(Targets, resolve_all);
+
+ if (o.pingscan || o.listscan) {
+ vector::iterator hI;
+
+ for(hI = Targets.begin(); hI != Targets.end(); hI++) {
+ log_write(LOG_XML, "");
+ write_host_status(*hI, resolve_all);
+ printmacinfo(*hI);
+ log_write(LOG_XML, "\n");
+ log_flush_all();
+ delete *hI;
+ }
+
+ Targets.clear();
+ continue;
+ }
+ } else {
break; /* Couldn't find any more targets */
+ }
// Our source must be set in decoy list because nexthost() call can
// change it (that issue really should be fixed when possible)
diff -urNb old.nmap.rev/nmap.h new.nmap.rev/nmap.h
--- old.nmap.rev/nmap.h Thu Nov 10 04:04:43 2005
+++ new.nmap.rev/nmap.h Thu Nov 10 04:04:44 2005
@@ -396,6 +396,8 @@
#define MAXHOSTNAMELEN 64
#endif
+#define DNS_PARALLELISM 10
+
#ifndef recvfrom6_t
# define recvfrom6_t int
#endif
diff -urNb old.nmap.rev/nmap_dns.cc new.nmap.rev/nmap_dns.cc
--- old.nmap.rev/nmap_dns.cc Wed Dec 31 16:00:00 1969
+++ new.nmap.rev/nmap_dns.cc Thu Nov 10 04:04:43 2005
@@ -0,0 +1,626 @@
+#include
+#include
+#include
+#include
+
+#include "nmap.h"
+#include "NmapOps.h"
+#include "nmap_dns.h"
+#include "nsock.h"
+#include "utils.h"
+
+extern NmapOps o;
+
+
+//------------------- Configuration Parameters ---------------------
+
+// The amount of time we wait for nsock_write() to complete before
+// retransmission. This should almost never happen. (in milliseconds)
+#define WRITE_TIMEOUT 100
+
+// This is the default max number of DNS requests to let each
+// server handle.
+#define DEFAULT_CAPACITY 10
+
+// These are the various retransmission intervals for each server
+// before we move on to the next DNS server. (in milliseconds)
+int read_timeouts[] = { 300, 500, 800, 2000 };
+
+
+
+//------------------- Internal Structures ---------------------
+
+typedef struct dns_server_s dns_server;
+typedef struct request_s request;
+
+struct dns_server_s {
+ char *ipaddr;
+ nsock_iod nsd;
+ int reqs_on_wire;
+ int capacity;
+ int write_busy;
+ std::list to_process;
+ std::list in_process;
+};
+
+struct request_s {
+ Target *targ;
+ struct timeval timeout;
+ int tries;
+ dns_server *first_server;
+ dns_server *curr_server;
+};
+
+
+//------------------- Globals ---------------------
+
+std::list servs;
+int total_reqs;
+nsock_pool dnspool=NULL;
+
+
+//------------------- Prototypes ---------------------
+
+void write_evt_handler(nsock_pool nsp, nsock_event evt, void *req_v);
+void do_possible_writes();
+
+
+
+
+//------------------- Read handling code ---------------------
+
+// After processing a DNS response, we search through the IPs we're
+// looking for and update their results as necessary.
+void process_result(unsigned long ia, char *result) {
+ std::list::iterator servI;
+ std::list::iterator reqI;
+ dns_server *tpserv;
+ request *tpreq;
+
+
+ for(servI = servs.begin(); servI != servs.end(); servI++) {
+ tpserv = *servI;
+
+ //for(reqI = tpserv->in_process.begin(); reqI != tpserv->in_process.end() && *reqI; reqI++) {
+ for(reqI = tpserv->in_process.begin(); reqI != tpserv->in_process.end(); reqI++) {
+ tpreq = *reqI;
+
+ if ((unsigned long) (tpreq->targ->v4host().s_addr) == ia) {
+ reqI--;
+ if (result) tpreq->targ->setHostName(result);
+ tpserv->in_process.remove(tpreq);
+ tpserv->reqs_on_wire--;
+ total_reqs--;
+
+ delete tpreq;
+ do_possible_writes();
+ return;
+ }
+ }
+ }
+}
+
+
+// Gets an IP address from a X.X.X.X.in-addr.arpa DNS
+// encoded string inside a packet.
+// ASSUMES NAME LENGTH/VALIDITY HAS ALREADY BEEN VERIFIED
+unsigned long parse_inaddr_arpa(char *buf) {
+ unsigned long ip=0;
+ int i, j;
+
+ for (i=3; i>=0; i--) {
+ if (buf[0] < 1 || buf[0] > 3) return 0;
+ for (j=1; j<=buf[0]; j++) if (!isdigit(buf[j])) return 0;
+
+ ip |= atoi(buf+1) << (8*i);
+ buf += buf[0] + 1;
+ }
+
+ if (strcasecmp(buf, "\x07in-addr\004arpa\0")) return 0;
+
+ return ip;
+}
+
+
+// Turns a DNS packet encoded name (see the RFC) and turns it into
+// a normal decimal separated hostname.
+// ASSUMES NAME LENGTH/VALIDITY HAS ALREADY BEEN VERIFIED
+int encoded_name_to_normal(char *buf, char *output, int outputsize){
+ while (buf[0]) {
+ if (buf[0] >= outputsize-1) return -1;
+ memcpy(output, buf+1, buf[0]);
+ outputsize -= buf[0];
+ output += buf[0];
+ buf += buf[0]+1;
+
+ if (buf[0]) {
+ *output++ = '.';
+ outputsize--;
+ } else {
+ *output = '\0';
+ }
+ }
+
+ return 0;
+}
+
+
+// Takes a pointer to the start of a DNS name inside a packet. It makes
+// sure that there is enough space in the name, deals with compression, etc.
+int advance_past_dns_name(char *buf, int buflen, int curbuf, int *nameloc) {
+ int compression=0;
+
+ if (curbuf <= 0 || curbuf >= buflen) return -1;
+
+ if ((buf[curbuf] & 0xc0)) {
+ // Need 2 bytes for compression info
+ if (curbuf + 1 >= buflen) return -1;
+
+ // Compression is OK
+ compression = curbuf+2;
+ curbuf = ((buf[curbuf+1] & 0xFF) + ((buf[curbuf] & 0xFF) << 8)) & 0x3FFF;
+ if (curbuf < 0 || curbuf >= buflen) return -1;
+ }
+
+ if (nameloc != NULL) *nameloc = curbuf;
+
+ while(buf[curbuf]) {
+ if (curbuf + buf[curbuf] >= buflen) return -1;
+ curbuf += buf[curbuf] + 1;
+ }
+
+ if (compression) return compression;
+ else return curbuf+1;
+}
+
+
+// Nsock read handler. One nsock read for each DNS server exists at each
+// time. This function uses various helper functions as defined above.
+void read_evt_handler(nsock_pool nsp, nsock_event evt, void *nothing) {
+ char *buf;
+ int buflen, curbuf=0;
+ int i, nameloc, rdlen, atype, aclass;
+ int nxdomain=0;
+ int queries, answers;
+
+ if (total_reqs > 1)
+ nsock_read(nsp, nse_iod(evt), read_evt_handler, -1, NULL);
+
+ if (nse_status(evt) != NSE_STATUS_SUCCESS) return;
+
+ buf = nse_readbuf(evt, &buflen);
+
+ // Size of header is 12, and we must have additional data as well
+ if (buflen <= 12) return;
+
+ // Check that this is a response, standard query, and that no truncation was performed
+ // 0xFA == 11111010 (we're not concerned with AA or RD bits)
+ if ((buf[2] & 0xFA) != 0x80) return;
+
+ // Check that Recursion is available, the zero field is all zeros
+ // and there is no error condition:
+ if ((buf[3] & 0xFF) != 0x80) {
+ if ((buf[3] & 0xF) == 3) nxdomain = 1;
+ else return;
+ }
+
+ queries = (buf[5] & 0xFF) + ((buf[4] & 0xFF) << 8);
+ answers = (buf[7] & 0xFF) + ((buf[6] & 0xFF) << 8);
+
+ // With a normal resolution, we should have 1+ queries and 1+ answers.
+ // If the domain doesn't resolve (NXDOMAIN) we should have 1+ queries and
+ // 0 answers:
+ if (nxdomain) {
+ if (queries <= 0 || answers > 0) return;
+ } else {
+ if (queries <= 0 || answers <= 0) return;
+ }
+
+ curbuf = 12;
+
+ // Need to safely skip past QUERY section
+
+ for (i=0; i= buflen) return;
+ curbuf += 4;
+
+ if (nxdomain) {
+ struct in_addr ia;
+ ia.s_addr = parse_inaddr_arpa(buf+nameloc);
+
+ //printf("NXDOMAIN <%s>\n", inet_ntoa(ia));
+ process_result(ia.s_addr, NULL);
+ }
+ }
+
+ // No answers if NXDOMAIN
+ if (nxdomain) return;
+
+ // We're now at the ANSWER section
+
+ for (i=0; i= buflen) return;
+
+ atype = (buf[curbuf+1] & 0xFF) + ((buf[curbuf+0] & 0xFF) << 8);
+ aclass = (buf[curbuf+3] & 0xFF) + ((buf[curbuf+2] & 0xFF) << 8);
+ rdlen = (buf[curbuf+9] & 0xFF) + ((buf[curbuf+8] & 0xFF) << 8);
+ curbuf += 10;
+
+ if (atype == 12 && aclass == 1) {
+ struct in_addr ia;
+ char outbuf[512];
+
+ ia.s_addr = parse_inaddr_arpa(buf+nameloc);
+ encoded_name_to_normal(buf+curbuf, outbuf, sizeof(outbuf));
+
+ //printf("MATCHED <%s> to <%s>\n", inet_ntoa(ia), outbuf);
+ process_result(ia.s_addr, outbuf);
+ }
+
+ curbuf += rdlen;
+
+ if (curbuf >= buflen) return;
+ }
+
+}
+
+
+
+
+//------------------- Write handling code ---------------------
+
+// Inserts an integer (endian non-specifically) into a DNS
+// packet.
+// Returns number of bytes written
+int add_integer_to_dns_packet(char *packet, unsigned long c) {
+ char tpnum[4];
+ int tplen;
+
+ sprintf(tpnum, "%ld", c);
+ tplen = strlen(tpnum);
+ packet[0] = (char) tplen;
+ memcpy(packet+1, tpnum, tplen);
+
+ return tplen+1;
+}
+
+
+// Takes a DNS request structure and actually puts it on the wire
+// (calls nsock_write()). Does various other tasks like recording
+// the time for the timeout.
+void put_dns_packet_on_wire(request *req) {
+ char packet[512];
+ int plen;
+ unsigned long ip;
+ struct timeval now, timeout;
+
+ ip = (unsigned long) req->targ->v4host().s_addr;
+
+ memcpy(packet, "\x99\x99\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00", 12);
+ plen = 12;
+
+ plen += add_integer_to_dns_packet(packet+plen, (ip>>24) & 0xFF);
+ plen += add_integer_to_dns_packet(packet+plen, (ip>>16) & 0xFF);
+ plen += add_integer_to_dns_packet(packet+plen, (ip>>8) & 0xFF);
+ plen += add_integer_to_dns_packet(packet+plen, ip & 0xFF);
+
+ memcpy(packet+plen, "\x07in-addr\004arpa\x00\x00\x0c\x00\x01", 18);
+ plen += 18;
+
+ req->curr_server->write_busy = 1;
+ req->curr_server->reqs_on_wire++;
+
+ memcpy(&now, nsock_gettimeofday(), sizeof(struct timeval));
+ TIMEVAL_MSEC_ADD(timeout, now, read_timeouts[req->tries]);
+ memcpy(&req->timeout, &timeout, sizeof(struct timeval));
+
+ req->tries++;
+
+ nsock_write(dnspool, req->curr_server->nsd, write_evt_handler, WRITE_TIMEOUT, req, packet, plen);
+}
+
+
+
+
+// Processes DNS packets that have timed out
+// Returns time until next read timeout
+int deal_with_timedout_reads() {
+ std::list::iterator servI;
+ std::list::iterator servItemp;
+ std::list::iterator reqI;
+ dns_server *tpserv;
+ request *tpreq;
+ struct timeval now;
+ int tp, min_timeout = INT_MAX;
+
+ memcpy(&now, nsock_gettimeofday(), sizeof(struct timeval));
+
+ for(servI = servs.begin(); servI != servs.end(); servI++) {
+ tpserv = *servI;
+
+ for(reqI = tpserv->in_process.begin(); reqI != tpserv->in_process.end(); reqI++) {
+ tpreq = *reqI;
+
+ tp = TIMEVAL_MSEC_SUBTRACT(tpreq->timeout, now);
+ if (tp > 0 && tp < min_timeout) min_timeout = tp;
+
+ if (tp <= 0) {
+ reqI--;
+ tpserv->in_process.remove(tpreq);
+ tpserv->reqs_on_wire--;
+
+ // If we've tried this server enough times, move to the next one
+ if (tpreq->tries >= (int) (sizeof(read_timeouts) / sizeof(int))) {
+ servItemp = servI;
+ servItemp++;
+
+ if (servItemp == servs.end()) servItemp = servs.begin();
+
+ tpreq->curr_server = *servItemp;
+ tpreq->tries = 0;
+
+ if (tpreq->curr_server == tpreq->first_server) {
+ // We've already tried all servers... give up
+ total_reqs--;
+ delete tpreq;
+ } else {
+ (*servItemp)->to_process.push_back(tpreq);
+ }
+ } else {
+ tpserv->to_process.push_back(tpreq);
+ }
+
+ continue;
+ }
+ }
+
+ }
+
+ if (min_timeout == INT_MAX) return 200;
+ else return min_timeout;
+
+}
+
+
+// Puts as many packets on the line as capacity will allow
+void do_possible_writes() {
+ std::list::iterator servI;
+ dns_server *tpserv;
+ request *tpreq;
+
+ for(servI = servs.begin(); servI != servs.end(); servI++) {
+ tpserv = *servI;
+
+ if (!tpserv->to_process.empty() && tpserv->write_busy == 0 && tpserv->reqs_on_wire < tpserv->capacity) {
+ tpreq = tpserv->to_process.front();
+ tpserv->to_process.pop_front();
+ put_dns_packet_on_wire(tpreq);
+ }
+
+ }
+
+}
+
+
+// nsock write handler
+void write_evt_handler(nsock_pool nsp, nsock_event evt, void *req_v) {
+ request *req = (request *) req_v;
+
+ req->curr_server->write_busy = 0;
+ req->curr_server->in_process.push_front(req);
+
+ do_possible_writes();
+}
+
+
+
+//------------------- DNS Server handling code ---------------------
+
+// nsock connect handler - Empty because it doesn't really need to do anything...
+void connect_evt_handler(nsock_pool nsp, nsock_event evt, void *servers) {
+}
+
+
+// Adds a DNS server to the dns_server list - Doesn't actually
+// do any connecting!
+void add_dns_server(char *ipaddr) {
+ dns_server *s;
+
+ s = new dns_server;
+
+ s->ipaddr = strdup(ipaddr);
+
+ servs.push_front(s);
+}
+
+
+// Creates a new nsi for each DNS server
+void connect_dns_servers() {
+ std::list::iterator serverI;
+ dns_server *s;
+ struct sockaddr_in ss;
+ int ss_len;
+
+ for(serverI = servs.begin(); serverI != servs.end(); serverI++) {
+ s = *serverI;
+
+ s->nsd = nsi_new(dnspool, NULL);
+ s->reqs_on_wire = 0;
+ s->capacity = DEFAULT_CAPACITY;
+ s->write_busy = 0;
+
+ ss_len = sizeof(struct sockaddr_in);
+ ss.sin_family = AF_INET;
+ inet_aton(s->ipaddr, &ss.sin_addr);
+
+ nsock_connect_udp(dnspool, s->nsd, connect_evt_handler, NULL, (struct sockaddr *) &ss, ss_len, 53);
+ nsock_read(dnspool, s->nsd, read_evt_handler, -1, NULL);
+ }
+
+}
+
+
+// Closes all nsis created in connect_dns_servers()
+void close_dns_servers() {
+ std::list::iterator serverI;
+
+ for(serverI = servs.begin(); serverI != servs.end(); serverI++) {
+ nsi_delete((*serverI)->nsd, NSOCK_PENDING_SILENT);
+ (*serverI)->to_process.clear();
+ (*serverI)->in_process.clear();
+ }
+
+}
+
+
+// Parses /etc/resolv.conf and adds all "nameserver"s with the
+// add_dns_server() function
+void parse_resolvdotconf() {
+ FILE *fp;
+ char buf[2048], *tp;
+ char ipaddr[16];
+
+ fp = fopen("/etc/resolv.conf", "r");
+ if (fp == NULL) {
+ fatal("Unable to open /etc/resolv.conf. Try using --system_dns");
+ }
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ tp = buf;
+
+ // Clip off comments #, \r, \n
+ while (*tp != '\r' && *tp != '\n' && *tp != '#') tp++;
+ *tp = '\0';
+
+ tp = buf;
+ // Skip any leading whitespace
+ while (*tp == ' ' || *tp == '\t') tp++;
+
+ if (sscanf(tp, "nameserver %15s", ipaddr) == 1) add_dns_server(ipaddr);
+ }
+
+ fclose(fp);
+}
+
+
+
+
+//------------------- Main loops ---------------------
+
+
+// Actual main loop
+void nmap_mass_rdns_core(std::vector Targets, int resolve_all) {
+
+ std::vector::iterator hostI;
+ std::list::iterator serverI;
+ request *tpreq;
+ int timeout;
+
+ if (o.mass_dns == false) {
+ Target *currenths;
+ struct sockaddr_storage ss;
+ size_t sslen;
+ char hostname[MAXHOSTNAMELEN + 1] = "";
+
+ for(hostI = Targets.begin(); hostI != Targets.end(); hostI++) {
+ currenths = *hostI;
+
+ if (((currenths->flags & HOST_UP) || resolve_all) && !o.noresolve) {
+ if (currenths->TargetSockAddr(&ss, &sslen) != 0)
+ fatal("Failed to get target socket address.");
+ if (getnameinfo((struct sockaddr *)&ss, sslen, hostname,
+ sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) {
+ currenths->setHostName(hostname);
+ }
+ }
+ }
+
+ return;
+ }
+
+ // If necessary, set up the dns server list from resolv.conf
+ // ...
+ if (servs.size() == 0) parse_resolvdotconf();
+
+
+ // If necessary, set up the /etc/hosts hashtable
+ // ...
+
+
+
+ total_reqs = 0;
+
+ // Set up the request structure
+ serverI = servs.begin();
+ for(hostI = Targets.begin(); hostI != Targets.end(); hostI++) {
+ if (!((*hostI)->flags & HOST_UP) && !resolve_all) continue;
+
+ tpreq = new request;
+ tpreq->targ = *hostI;
+ tpreq->tries = 0;
+
+ tpreq->first_server = tpreq->curr_server = *serverI;
+ (*serverI)->to_process.push_back(tpreq);
+
+ serverI++;
+ if (serverI == servs.end()) serverI = servs.begin();
+
+ total_reqs++;
+ }
+
+ if (total_reqs == 0) return;
+
+ // And finally, do it!
+
+ //FIXME: error check
+ if ((dnspool = nsp_new(NULL)) == NULL) exit(1);
+
+ connect_dns_servers();
+
+ while (total_reqs > 0) {
+ timeout = deal_with_timedout_reads();
+
+ do_possible_writes();
+
+ if (total_reqs <= 0) break;
+
+ nsock_loop(dnspool, timeout);
+ }
+
+ close_dns_servers();
+
+ nsp_delete(dnspool);
+
+}
+
+
+
+// Publicly available function. Basically just a wrapper so we
+// can record time information
+void nmap_mass_rdns(std::vector Targets, int resolve_all) {
+
+ struct timeval starttv, now;
+
+ gettimeofday(&starttv, NULL);
+
+ nmap_mass_rdns_core(Targets, resolve_all);
+
+ gettimeofday(&now, NULL);
+
+ if (o.verbose) {
+ log_write(LOG_STDOUT, "DNS resolution of %d IPs took %.2fs. Mode: %s\n",
+ Targets.size(),
+ TIMEVAL_MSEC_SUBTRACT(now, starttv) / 1000.0,
+ o.mass_dns ? "Async" : "System");
+ }
+
+}
diff -urNb old.nmap.rev/nmap_dns.h new.nmap.rev/nmap_dns.h
--- old.nmap.rev/nmap_dns.h Wed Dec 31 16:00:00 1969
+++ new.nmap.rev/nmap_dns.h Thu Nov 10 04:04:44 2005
@@ -0,0 +1,4 @@
+#include "Target.h"
+#include
+
+void nmap_mass_rdns(std::vector Targets, int resolve_all);