mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Simplify mass_dns for the case of requesting A and AAAA records
This commit is contained in:
@@ -115,7 +115,7 @@ public:
|
|||||||
* NetBlock subclass, override this method. Otherwise, it's safe to reassign
|
* NetBlock subclass, override this method. Otherwise, it's safe to reassign
|
||||||
* the return value to the pointer that this method was called through.
|
* the return value to the pointer that this method was called through.
|
||||||
* On error, return NULL. */
|
* On error, return NULL. */
|
||||||
virtual NetBlock *resolve(const DNS::Request &reqA, const DNS::Request &reqAAAA) { return this; }
|
virtual NetBlock *resolve(const DNS::Request &req) { return this; }
|
||||||
virtual void reject_last_host() {}
|
virtual void reject_last_host() {}
|
||||||
virtual bool next(struct sockaddr_storage *ss, size_t *sslen) = 0;
|
virtual bool next(struct sockaddr_storage *ss, size_t *sslen) = 0;
|
||||||
virtual void apply_netmask(int bits) = 0;
|
virtual void apply_netmask(int bits) = 0;
|
||||||
@@ -174,7 +174,7 @@ public:
|
|||||||
int af;
|
int af;
|
||||||
int bits;
|
int bits;
|
||||||
|
|
||||||
NetBlock *resolve(const DNS::Request &reqA, const DNS::Request &reqAAAA);
|
NetBlock *resolve(const DNS::Request &req);
|
||||||
|
|
||||||
bool next(struct sockaddr_storage *ss, size_t *sslen);
|
bool next(struct sockaddr_storage *ss, size_t *sslen);
|
||||||
void apply_netmask(int bits);
|
void apply_netmask(int bits);
|
||||||
@@ -306,9 +306,7 @@ static NetBlock *parse_expr_without_netmask(const char *hostexp, int af, std::ve
|
|||||||
DNS::Request req;
|
DNS::Request req;
|
||||||
req.name = hostexp;
|
req.name = hostexp;
|
||||||
req.userdata = nb;
|
req.userdata = nb;
|
||||||
req.type = DNS::A;
|
req.type = DNS::ANY;
|
||||||
requests.push_back(req);
|
|
||||||
req.type = DNS::AAAA;
|
|
||||||
requests.push_back(req);
|
requests.push_back(req);
|
||||||
return nb;
|
return nb;
|
||||||
}
|
}
|
||||||
@@ -706,22 +704,19 @@ std::string NetBlockIPv6Netmask::str() const {
|
|||||||
return result.str();
|
return result.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
NetBlock *NetBlockHostname::resolve(const DNS::Request &reqA, const DNS::Request &reqAAAA) {
|
NetBlock *NetBlockHostname::resolve(const DNS::Request &req) {
|
||||||
std::list<struct sockaddr_storage> resolvedaddrs;
|
std::list<struct sockaddr_storage> resolvedaddrs;
|
||||||
std::list<struct sockaddr_storage> unscanned_addrs;
|
std::list<struct sockaddr_storage> unscanned_addrs;
|
||||||
NetBlock *netblock;
|
NetBlock *netblock;
|
||||||
|
|
||||||
const DNS::Request &req_same_fam = (af == AF_INET ? reqA : reqAAAA);
|
for (size_t i = 0; i < req.ssv.size(); i++) {
|
||||||
const DNS::Request &req_other_fam = (af == AF_INET ? reqAAAA : reqA);
|
const struct sockaddr_storage &ss = req.ssv[i];
|
||||||
if (!req_same_fam.ssv.empty()) {
|
if (ss.ss_family == af && (o.resolve_all || resolvedaddrs.empty())) {
|
||||||
resolvedaddrs.push_back(req_same_fam.ssv[0]);
|
resolvedaddrs.push_back(ss);
|
||||||
std::list<struct sockaddr_storage> &remainder = o.resolve_all ? resolvedaddrs : unscanned_addrs;
|
}
|
||||||
for (size_t i = 1; i < req_same_fam.ssv.size(); i++) {
|
else {
|
||||||
remainder.push_back(req_same_fam.ssv[i]);
|
unscanned_addrs.push_back(ss);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for (size_t i = 0; i < req_other_fam.ssv.size(); i++) {
|
|
||||||
unscanned_addrs.push_back(req_other_fam.ssv[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resolvedaddrs.empty()) {
|
if (resolvedaddrs.empty()) {
|
||||||
@@ -825,7 +820,7 @@ bool TargetGroup::load_expressions(HostGroupState *hs, int af) {
|
|||||||
assert(netblocks.empty());
|
assert(netblocks.empty());
|
||||||
const char *target_expr = NULL;
|
const char *target_expr = NULL;
|
||||||
std::vector<DNS::Request> requests;
|
std::vector<DNS::Request> requests;
|
||||||
requests.reserve(EXPR_PARSE_BATCH_SZ/2);
|
requests.reserve(EXPR_PARSE_BATCH_SZ/4);
|
||||||
while (netblocks.size() < EXPR_PARSE_BATCH_SZ
|
while (netblocks.size() < EXPR_PARSE_BATCH_SZ
|
||||||
&& NULL != (target_expr = hs->next_expression())) {
|
&& NULL != (target_expr = hs->next_expression())) {
|
||||||
NetBlock *nb = NetBlock::parse_expr(target_expr, af, requests);
|
NetBlock *nb = NetBlock::parse_expr(target_expr, af, requests);
|
||||||
@@ -845,12 +840,9 @@ bool TargetGroup::load_expressions(HostGroupState *hs, int af) {
|
|||||||
std::list<NetBlock *>::iterator nb_it = netblocks.begin();
|
std::list<NetBlock *>::iterator nb_it = netblocks.begin();
|
||||||
for (std::vector<DNS::Request>::const_iterator rit = requests.begin();
|
for (std::vector<DNS::Request>::const_iterator rit = requests.begin();
|
||||||
rit != requests.end(); rit++) {
|
rit != requests.end(); rit++) {
|
||||||
const DNS::Request &reqA = *rit++;
|
const DNS::Request &req = *rit;
|
||||||
const DNS::Request &reqAAAA = *rit;
|
NetBlock *nb_old = (NetBlock *) req.userdata;
|
||||||
NetBlock *nb_old = (NetBlock *) reqA.userdata;
|
NetBlock *nb_new = nb_old->resolve(req);
|
||||||
assert(reqA.userdata == reqAAAA.userdata);
|
|
||||||
assert(reqA.type == DNS::A && reqAAAA.type == DNS::AAAA);
|
|
||||||
NetBlock *nb_new = nb_old->resolve(reqA, reqAAAA);
|
|
||||||
nb_it = std::find(nb_it, netblocks.end(), nb_old);
|
nb_it = std::find(nb_it, netblocks.end(), nb_old);
|
||||||
|
|
||||||
if (nb_new == NULL) {
|
if (nb_new == NULL) {
|
||||||
|
|||||||
114
nmap_dns.cc
114
nmap_dns.cc
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* nmap_dns.cc -- Handles parallel reverse DNS resolution for target IPs *
|
* nmap_dns.cc -- Handles parallel DNS resolution for target IPs *
|
||||||
* *
|
* *
|
||||||
***********************IMPORTANT NMAP LICENSE TERMS************************
|
***********************IMPORTANT NMAP LICENSE TERMS************************
|
||||||
*
|
*
|
||||||
@@ -225,6 +225,7 @@ struct request {
|
|||||||
dns_server *first_server;
|
dns_server *first_server;
|
||||||
dns_server *curr_server;
|
dns_server *curr_server;
|
||||||
u16 id;
|
u16 id;
|
||||||
|
bool alt_req;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*keeps record of a request going through a particular DNS server
|
/*keeps record of a request going through a particular DNS server
|
||||||
@@ -469,6 +470,13 @@ static void write_evt_handler(nsock_pool nsp, nsock_event evt, void *req_v) {
|
|||||||
do_possible_writes();
|
do_possible_writes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DNS::RECORD_TYPE wire_type(DNS::RECORD_TYPE t) {
|
||||||
|
if (t == DNS::ANY) {
|
||||||
|
return DNS::A;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
// Takes a DNS request structure and actually puts it on the wire
|
// Takes a DNS request structure and actually puts it on the wire
|
||||||
// (calls nsock_write()). Does various other tasks like recording
|
// (calls nsock_write()). Does various other tasks like recording
|
||||||
// the time for the timeout.
|
// the time for the timeout.
|
||||||
@@ -485,9 +493,10 @@ static void put_dns_packet_on_wire(request *req) {
|
|||||||
DNS::Request &reqt = *req->targ;
|
DNS::Request &reqt = *req->targ;
|
||||||
|
|
||||||
switch(reqt.type) {
|
switch(reqt.type) {
|
||||||
|
case DNS::ANY:
|
||||||
case DNS::A:
|
case DNS::A:
|
||||||
case DNS::AAAA:
|
case DNS::AAAA:
|
||||||
plen = DNS::Factory::buildSimpleRequest(reqt.name, reqt.type, packet, maxlen);
|
plen = DNS::Factory::buildSimpleRequest(reqt.name, wire_type(reqt.type), packet, maxlen);
|
||||||
break;
|
break;
|
||||||
case DNS::PTR:
|
case DNS::PTR:
|
||||||
assert(reqt.ssv.size() > 0);
|
assert(reqt.ssv.size() > 0);
|
||||||
@@ -604,7 +613,7 @@ static void process_request(int action, info &reqinfo) {
|
|||||||
server->in_process.remove(tpreq);
|
server->in_process.remove(tpreq);
|
||||||
server->reqs_on_wire--;
|
server->reqs_on_wire--;
|
||||||
total_reqs--;
|
total_reqs--;
|
||||||
if (action == ACTION_SYSTEM_RESOLVE) {
|
if (action == ACTION_SYSTEM_RESOLVE && !tpreq->alt_req) {
|
||||||
deferred_reqs.push_back(tpreq);
|
deferred_reqs.push_back(tpreq);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -628,6 +637,14 @@ static void process_request(int action, info &reqinfo) {
|
|||||||
static bool process_result(const std::string &name, const DNS::Record *rr, info &reqinfo, bool already_matched)
|
static bool process_result(const std::string &name, const DNS::Record *rr, info &reqinfo, bool already_matched)
|
||||||
{
|
{
|
||||||
DNS::Request *reqt = reqinfo.tpreq->targ;
|
DNS::Request *reqt = reqinfo.tpreq->targ;
|
||||||
|
std::vector<struct sockaddr_storage> *ssv;
|
||||||
|
if (reqinfo.tpreq->alt_req) {
|
||||||
|
DNS::Request *alt_req = (DNS::Request *) reqinfo.tpreq->targ->userdata;
|
||||||
|
ssv = &alt_req->ssv;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ssv = &reqt->ssv;
|
||||||
|
}
|
||||||
const struct sockaddr_storage *ss = NULL;
|
const struct sockaddr_storage *ss = NULL;
|
||||||
const DNS::A_Record *a_rec = NULL;
|
const DNS::A_Record *a_rec = NULL;
|
||||||
sockaddr_storage ip;
|
sockaddr_storage ip;
|
||||||
@@ -635,11 +652,12 @@ static bool process_result(const std::string &name, const DNS::Record *rr, info
|
|||||||
switch (reqt->type) {
|
switch (reqt->type) {
|
||||||
case DNS::A:
|
case DNS::A:
|
||||||
case DNS::AAAA:
|
case DNS::AAAA:
|
||||||
|
case DNS::ANY:
|
||||||
if (!already_matched && name != reqt->name) {
|
if (!already_matched && name != reqt->name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
a_rec = static_cast<const DNS::A_Record *>(rr);
|
a_rec = static_cast<const DNS::A_Record *>(rr);
|
||||||
reqt->ssv.push_back(a_rec->value);
|
ssv->push_back(a_rec->value);
|
||||||
if (o.debugging >= TRACE_DEBUG_LEVEL)
|
if (o.debugging >= TRACE_DEBUG_LEVEL)
|
||||||
{
|
{
|
||||||
log_write(LOG_STDOUT, "mass_dns: OK MATCHED <%s> to <%s>\n",
|
log_write(LOG_STDOUT, "mass_dns: OK MATCHED <%s> to <%s>\n",
|
||||||
@@ -744,7 +762,7 @@ static void read_evt_handler(nsock_pool nsp, nsock_event evt, void *) {
|
|||||||
const DNS::Answer &a = *it;
|
const DNS::Answer &a = *it;
|
||||||
if(a.record_class == DNS::CLASS_IN)
|
if(a.record_class == DNS::CLASS_IN)
|
||||||
{
|
{
|
||||||
if (reqt->type == a.record_type) {
|
if (wire_type(reqt->type) == a.record_type) {
|
||||||
processing_successful = process_result(a.name, a.record, reqinfo, a.name == alias);
|
processing_successful = process_result(a.name, a.record, reqinfo, a.name == alias);
|
||||||
if (!processing_successful && o.debugging) {
|
if (!processing_successful && o.debugging) {
|
||||||
log_write(LOG_STDOUT, "mass_dns: Mismatched record for request %s\n", reqt->repr());
|
log_write(LOG_STDOUT, "mass_dns: Mismatched record for request %s\n", reqt->repr());
|
||||||
@@ -1077,34 +1095,42 @@ static bool system_resolve(DNS::Request &reqt)
|
|||||||
int af = AF_INET;
|
int af = AF_INET;
|
||||||
struct addrinfo *ai_result = NULL, *ai = NULL;
|
struct addrinfo *ai_result = NULL, *ai = NULL;
|
||||||
|
|
||||||
switch (reqt.type) {
|
if (reqt.type == DNS::PTR) {
|
||||||
case DNS::PTR:
|
assert(reqt.ssv.size() > 0);
|
||||||
assert(reqt.ssv.size() > 0);
|
if (getnameinfo((const struct sockaddr *) &reqt.ssv.front(),
|
||||||
if (getnameinfo((const struct sockaddr *) &reqt.ssv.front(),
|
sizeof(sockaddr_storage), hostname,
|
||||||
sizeof(sockaddr_storage), hostname,
|
sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) {
|
||||||
sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) {
|
reqt.name = hostname;
|
||||||
reqt.name = hostname;
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DNS::AAAA:
|
|
||||||
af = AF_INET6;
|
|
||||||
case DNS::A:
|
|
||||||
ai_result = resolve_all(reqt.name.c_str(), af);
|
|
||||||
for (ai = ai_result; ai != NULL; ai = ai->ai_next) {
|
|
||||||
if (ai->ai_addr->sa_family == af && ai->ai_addrlen <= sizeof(struct sockaddr_storage)) {
|
|
||||||
reqt.ssv.push_back(*(struct sockaddr_storage *)ai->ai_addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ai_result != NULL)
|
|
||||||
freeaddrinfo(ai_result);
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error("System DNS resolution of %s could not be performed.\n", reqt.repr());
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return false;
|
else {
|
||||||
|
switch (reqt.type) {
|
||||||
|
case DNS::A:
|
||||||
|
af = AF_INET;
|
||||||
|
break;
|
||||||
|
case DNS::AAAA:
|
||||||
|
af = AF_INET6;
|
||||||
|
break;
|
||||||
|
case DNS::ANY:
|
||||||
|
af = AF_UNSPEC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("System DNS resolution of %s could not be performed.\n", reqt.repr());
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ai_result = resolve_all(reqt.name.c_str(), af);
|
||||||
|
for (ai = ai_result; ai != NULL; ai = ai->ai_next) {
|
||||||
|
if (ai->ai_addrlen <= sizeof(struct sockaddr_storage)) {
|
||||||
|
reqt.ssv.push_back(*(struct sockaddr_storage *)ai->ai_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ai_result != NULL)
|
||||||
|
freeaddrinfo(ai_result);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------- Main loops ---------------------
|
//------------------- Main loops ---------------------
|
||||||
@@ -1136,11 +1162,9 @@ static void nmap_mass_dns_core(DNS::Request *requests, int num_requests) {
|
|||||||
total_reqs = 0;
|
total_reqs = 0;
|
||||||
|
|
||||||
// Set up the request structure
|
// Set up the request structure
|
||||||
std::string *prev = NULL;
|
|
||||||
for (int i=0; i < num_requests; i++)
|
for (int i=0; i < num_requests; i++)
|
||||||
{
|
{
|
||||||
DNS::Request &reqt = requests[i];
|
DNS::Request &reqt = requests[i];
|
||||||
assert(reqt.type == DNS::PTR || reqt.type == DNS::A || reqt.type == DNS::AAAA);
|
|
||||||
|
|
||||||
// See if it's cached
|
// See if it's cached
|
||||||
if (reqt.type == DNS::PTR) {
|
if (reqt.type == DNS::PTR) {
|
||||||
@@ -1154,14 +1178,25 @@ static void nmap_mass_dns_core(DNS::Request *requests, int num_requests) {
|
|||||||
tpreq->targ = &reqt;
|
tpreq->targ = &reqt;
|
||||||
tpreq->tries = 0;
|
tpreq->tries = 0;
|
||||||
tpreq->servers_tried = 0;
|
tpreq->servers_tried = 0;
|
||||||
|
tpreq->alt_req = false;
|
||||||
|
|
||||||
new_reqs.push_back(tpreq);
|
new_reqs.push_back(tpreq);
|
||||||
|
|
||||||
if (!prev || *prev != reqt.name) {
|
|
||||||
stat_actual++;
|
|
||||||
}
|
|
||||||
total_reqs++;
|
total_reqs++;
|
||||||
prev = &reqt.name;
|
|
||||||
|
if (reqt.type == DNS::ANY) {
|
||||||
|
DNS::Request *req_aaaa = new DNS::Request;
|
||||||
|
req_aaaa->type = DNS::AAAA;
|
||||||
|
req_aaaa->name = reqt.name;
|
||||||
|
req_aaaa->userdata = &reqt;
|
||||||
|
request *tpreq_alt = new request;
|
||||||
|
*tpreq_alt = *tpreq;
|
||||||
|
tpreq_alt->targ = req_aaaa;
|
||||||
|
tpreq_alt->alt_req = true;
|
||||||
|
new_reqs.push_back(tpreq_alt);
|
||||||
|
total_reqs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
stat_actual++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (total_reqs == 0 || servs.size() == 0) return;
|
if (total_reqs == 0 || servs.size() == 0) return;
|
||||||
@@ -1789,6 +1824,7 @@ const char *DNS::Request::repr()
|
|||||||
break;
|
break;
|
||||||
case DNS::A:
|
case DNS::A:
|
||||||
case DNS::AAAA:
|
case DNS::AAAA:
|
||||||
|
case DNS::ANY:
|
||||||
return name.c_str();
|
return name.c_str();
|
||||||
break;
|
break;
|
||||||
case DNS::PTR:
|
case DNS::PTR:
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ typedef enum {
|
|||||||
CNAME = 5,
|
CNAME = 5,
|
||||||
PTR = 12,
|
PTR = 12,
|
||||||
AAAA = 28,
|
AAAA = 28,
|
||||||
|
ANY = 255, // Internally defined as "A and AAAA"
|
||||||
} RECORD_TYPE;
|
} RECORD_TYPE;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
Reference in New Issue
Block a user