1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 12:41:29 +00:00

Merge from svn://svn.insecure.org/nmap-exp/david/nmap-traceroute. This

brings in a new, faster, parallel version of traceroute.
This commit is contained in:
david
2009-09-17 00:03:46 +00:00
parent 86e7a63bf6
commit 577a1be0e7
11 changed files with 1472 additions and 1597 deletions

View File

@@ -116,6 +116,7 @@ void Target::Initialize() {
FPR = NULL; FPR = NULL;
osscan_flag = OS_NOTPERF; osscan_flag = OS_NOTPERF;
weird_responses = flags = 0; weird_responses = flags = 0;
traceroute_probespec.type = PS_NONE;
memset(&to, 0, sizeof(to)); memset(&to, 0, sizeof(to));
memset(&targetsock, 0, sizeof(targetsock)); memset(&targetsock, 0, sizeof(targetsock));
memset(&sourcesock, 0, sizeof(sourcesock)); memset(&sourcesock, 0, sizeof(sourcesock));
@@ -228,7 +229,7 @@ void Target::setTargetSockAddr(struct sockaddr_storage *ss, size_t ss_len) {
} }
// Returns IPv4 host address or {0} if unavailable. // Returns IPv4 host address or {0} if unavailable.
struct in_addr Target::v4host() { struct in_addr Target::v4host() const {
const struct in_addr *addy = v4hostip(); const struct in_addr *addy = v4hostip();
struct in_addr in; struct in_addr in;
if (addy) return *addy; if (addy) return *addy;

View File

@@ -106,6 +106,8 @@
#include "tcpip.h" #include "tcpip.h"
#include "scan_engine.h" #include "scan_engine.h"
#include <list>
#ifndef INET6_ADDRSTRLEN #ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 46 #define INET6_ADDRSTRLEN 46
#endif #endif
@@ -131,6 +133,22 @@ struct host_timeout_nfo {
time_t host_start, host_end; /* The absolute start and end for this host */ time_t host_start, host_end; /* The absolute start and end for this host */
}; };
struct TracerouteHop {
struct sockaddr_storage tag;
bool timedout;
std::string name;
struct sockaddr_storage addr;
int ttl;
float rtt; /* In milliseconds. */
int display_name(char *buf, size_t len) {
if (name.empty())
return Snprintf(buf, len, "%s", inet_ntop_ez(&addr, sizeof(addr)));
else
return Snprintf(buf, len, "%s (%s)", name.c_str(), inet_ntop_ez(&addr, sizeof(addr)));
}
};
class Target { class Target {
public: /* For now ... a lot of the data members should be made private */ public: /* For now ... a lot of the data members should be made private */
Target(); Target();
@@ -148,7 +166,7 @@ class Target {
to sockaddr_storage */ to sockaddr_storage */
void setTargetSockAddr(struct sockaddr_storage *ss, size_t ss_len); void setTargetSockAddr(struct sockaddr_storage *ss, size_t ss_len);
// Returns IPv4 target host address or {0} if unavailable. // Returns IPv4 target host address or {0} if unavailable.
struct in_addr v4host(); struct in_addr v4host() const;
const struct in_addr *v4hostip() const; const struct in_addr *v4hostip() const;
/* The source address used to reach the target */ /* The source address used to reach the target */
int SourceSockAddr(struct sockaddr_storage *ss, size_t *ss_len); int SourceSockAddr(struct sockaddr_storage *ss, size_t *ss_len);
@@ -158,7 +176,7 @@ class Target {
struct in_addr v4source() const; struct in_addr v4source() const;
const struct in_addr *v4sourceip() const; const struct in_addr *v4sourceip() const;
/* The IPv4 or IPv6 literal string for the target host */ /* The IPv4 or IPv6 literal string for the target host */
const char *targetipstr() { return targetipstring; } const char *targetipstr() const { return targetipstring; }
/* Give the name from the last setHostName() call, which should be /* Give the name from the last setHostName() call, which should be
the name obtained from reverse-resolution (PTR query) of the IP (v4 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 or v6). If the name has not been set, or was set to NULL, an empty
@@ -262,6 +280,9 @@ class Target {
char *hostname; // Null if unable to resolve or unset char *hostname; // Null if unable to resolve or unset
char * targetname; // The name of the target host given on the commmand line if it is a named host char * targetname; // The name of the target host given on the commmand line if it is a named host
struct probespec traceroute_probespec;
std::list <TracerouteHop> traceroute_hops;
#ifndef NOLUA #ifndef NOLUA
ScriptResults scriptResults; ScriptResults scriptResults;
#endif #endif

View File

@@ -236,6 +236,6 @@ struct scan_lists {
int prot_count; int prot_count;
}; };
typedef enum { STYPE_UNKNOWN, HOST_DISCOVERY, ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, SCTP_INIT_SCAN, SCTP_COOKIE_ECHO_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_SCAN, TRACEROUTE, REF_TRACEROUTE}stype; typedef enum { STYPE_UNKNOWN, HOST_DISCOVERY, ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, SCTP_INIT_SCAN, SCTP_COOKIE_ECHO_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_SCAN, TRACEROUTE}stype;
#endif /*GLOBAL_STRUCTURES_H */ #endif /*GLOBAL_STRUCTURES_H */

25
nmap.cc
View File

@@ -569,7 +569,6 @@ int nmap_main(int argc, char *argv[]) {
char *endptr = NULL; char *endptr = NULL;
struct scan_lists ports = { 0 }; struct scan_lists ports = { 0 };
TargetGroup *exclude_group = NULL; TargetGroup *exclude_group = NULL;
Traceroute *troute = NULL;
char myname[MAXHOSTNAMELEN + 1]; char myname[MAXHOSTNAMELEN + 1];
#if (defined(IN_ADDR_DEEPSTRUCT) || defined( SOLARIS)) #if (defined(IN_ADDR_DEEPSTRUCT) || defined( SOLARIS))
/* Note that struct in_addr in solaris is 3 levels deep just to store an /* Note that struct in_addr in solaris is 3 levels deep just to store an
@@ -1811,9 +1810,7 @@ int nmap_main(int argc, char *argv[]) {
if(o.traceroute && o.noportscan) { if(o.traceroute && o.noportscan) {
/* Assume that all targets in a group use the same device */ /* Assume that all targets in a group use the same device */
vector<Target *>::iterator it; vector<Target *>::iterator it;
troute = new Traceroute(Targets[0]->deviceName(), Targets[0]->ifType(), &ports); traceroute(Targets);
troute->trace(Targets);
troute->resolveHops();
/* print ping traceroutes, making sure the reference /* print ping traceroutes, making sure the reference
* trace is first */ * trace is first */
@@ -1823,7 +1820,7 @@ int nmap_main(int argc, char *argv[]) {
log_write(LOG_XML, "<host>"); log_write(LOG_XML, "<host>");
write_host_status(currenths, o.resolve_all); write_host_status(currenths, o.resolve_all);
printmacinfo(currenths); printmacinfo(currenths);
troute->outputTarget(currenths); printtraceroute(currenths);
log_write(LOG_XML, "</host>\n"); log_write(LOG_XML, "</host>\n");
log_write(LOG_PLAIN,"\n"); log_write(LOG_PLAIN,"\n");
} }
@@ -1834,8 +1831,6 @@ int nmap_main(int argc, char *argv[]) {
} }
o.numhosts_scanning = 0; o.numhosts_scanning = 0;
log_flush_all(); log_flush_all();
delete troute;
troute = NULL;
continue; continue;
} }
@@ -1906,11 +1901,8 @@ int nmap_main(int argc, char *argv[]) {
if (o.osscan == OS_SCAN_DEFAULT) if (o.osscan == OS_SCAN_DEFAULT)
os_scan2(Targets); os_scan2(Targets);
if(o.traceroute) { if(o.traceroute)
troute = new Traceroute(Targets[0]->deviceName(), Targets[0]->ifType(), &ports); traceroute(Targets);
troute->trace(Targets);
troute->resolveHops();
}
if (o.servicescan || o.rpcscan) { if (o.servicescan || o.rpcscan) {
/* This scantype must be after any TCP or UDP scans since it /* This scantype must be after any TCP or UDP scans since it
@@ -1949,8 +1941,8 @@ int nmap_main(int argc, char *argv[]) {
#endif #endif
} }
if(troute) if(o.traceroute)
troute->outputTarget(currenths); printtraceroute(currenths);
if (o.debugging) if (o.debugging)
log_write(LOG_STDOUT, "Final times for host: srtt: %d rttvar: %d to: %d\n", log_write(LOG_STDOUT, "Final times for host: srtt: %d rttvar: %d to: %d\n",
@@ -1973,9 +1965,6 @@ int nmap_main(int argc, char *argv[]) {
o.numhosts_scanning = 0; o.numhosts_scanning = 0;
} while(!o.max_ips_to_scan || o.max_ips_to_scan > o.numhosts_scanned); } while(!o.max_ips_to_scan || o.max_ips_to_scan > o.numhosts_scanned);
if(troute)
delete troute;
delete hstate; delete hstate;
if (exclude_group) if (exclude_group)
delete[] exclude_group; delete[] exclude_group;
@@ -2027,6 +2016,7 @@ void nmap_free_mem() {
close_nse(); close_nse();
free(o.scriptargs); free(o.scriptargs);
#endif #endif
traceroute_hop_cache_clear();
} }
/* Reads in a (normal or machine format) Nmap log file and gathers enough /* Reads in a (normal or machine format) Nmap log file and gathers enough
@@ -2646,7 +2636,6 @@ const char *scantype2str(stype scantype) {
case OS_SCAN: return "OS Scan"; break; case OS_SCAN: return "OS Scan"; break;
case SCRIPT_SCAN: return "Script Scan"; break; case SCRIPT_SCAN: return "Script Scan"; break;
case TRACEROUTE: return "Traceroute" ; break; case TRACEROUTE: return "Traceroute" ; break;
case REF_TRACEROUTE: return "Reference Traceroute"; break;
default: assert(0); break; default: assert(0); break;
} }

View File

@@ -88,6 +88,8 @@
class Target; class Target;
#include "nbase.h"
#include <string> #include <string>
#include <list> #include <list>

156
output.cc
View File

@@ -1897,6 +1897,162 @@ void printhostscriptresults(Target *currenths) {
} }
#endif #endif
/* Print a table with traceroute hops. */
static void printtraceroute_normal(Target *currenths) {
static const int HOP_COL = 0, RTT_COL = 1, HOST_COL = 2;
NmapOutputTable Tbl(currenths->traceroute_hops.size() + 1, 3);
struct probespec probe;
list <TracerouteHop>::iterator it;
int row;
/* No trace, must be localhost. */
if (currenths->traceroute_hops.size() == 0)
return;
/* Print header. */
log_write(LOG_PLAIN, "\n");
probe = currenths->traceroute_probespec;
if (probe.type == PS_TCP) {
log_write(LOG_PLAIN, "TRACEROUTE (using port %d/%s)\n",
probe.pd.tcp.dport, proto2ascii(probe.proto));
} else if (probe.type == PS_UDP) {
log_write(LOG_PLAIN, "TRACEROUTE (using port %d/%s)\n",
probe.pd.udp.dport, proto2ascii(probe.proto));
} else if (probe.type == PS_SCTP) {
log_write(LOG_PLAIN, "TRACEROUTE (using port %d/%s)\n",
probe.pd.sctp.dport, proto2ascii(probe.proto));
} else if (probe.type == PS_ICMP || probe.type == PS_PROTO) {
struct protoent *proto = nmap_getprotbynum(htons(probe.proto));
log_write(LOG_PLAIN, "TRACEROUTE (using proto %d/%s)\n",
probe.proto, proto ? proto->p_name : "unknown");
}
row = 0;
Tbl.addItem(row, HOP_COL, false, "HOP");
Tbl.addItem(row, RTT_COL, false, "RTT");
Tbl.addItem(row, HOST_COL, false, "ADDRESS");
row++;
it = currenths->traceroute_hops.begin();
if (!o.debugging) {
/* Consolidate shared hops. */
TracerouteHop *shared_hop = NULL;
struct sockaddr_storage addr;
size_t sslen;
sslen = sizeof(addr);
currenths->TargetSockAddr(&addr, &sslen);
while (it != currenths->traceroute_hops.end()
&& sockaddr_storage_cmp(&it->tag, &addr) != 0) {
shared_hop = &*it;
it++;
}
if (shared_hop != NULL) {
Tbl.addItem(row, HOP_COL, false, "-");
if (shared_hop->ttl == 1) {
Tbl.addItemFormatted(row, RTT_COL, true, "Hop 1 is the same as for %s",
inet_ntop_ez(&shared_hop->tag, sizeof(shared_hop->tag)));
} else if (shared_hop->ttl > 1) {
Tbl.addItemFormatted(row, RTT_COL, true,
"Hops 1-%d are the same as for %s", shared_hop->ttl,
inet_ntop_ez(&shared_hop->tag, sizeof(shared_hop->tag)));
}
row++;
}
}
while (it != currenths->traceroute_hops.end()) {
Tbl.addItemFormatted(row, HOP_COL, false, "%d", it->ttl);
if (it->timedout) {
if (o.debugging) {
Tbl.addItem(row, RTT_COL, false, "...");
it++;
} else {
/* The beginning and end of timeout consolidation. */
int begin_ttl, end_ttl;
begin_ttl = end_ttl = it->ttl;
for (; it != currenths->traceroute_hops.end() && it->timedout; it++)
end_ttl = it->ttl;
if (begin_ttl == end_ttl)
Tbl.addItem(row, RTT_COL, false, "...");
else
Tbl.addItemFormatted(row, RTT_COL, false, "... %d", end_ttl);
}
row++;
} else {
char namebuf[256];
/* Normal hop output. */
it->display_name(namebuf, sizeof(namebuf));
Tbl.addItemFormatted(row, RTT_COL, false, "%.2f ms", it->rtt);
Tbl.addItemFormatted(row, HOST_COL, false, "%s", namebuf);
row++;
it++;
}
}
log_write(LOG_PLAIN, "%s", Tbl.printableTable(NULL));
log_flush(LOG_PLAIN);
}
static void printtraceroute_xml(Target *currenths) {
struct probespec probe;
list <TracerouteHop>::iterator it;
/* No trace, must be localhost. */
if (currenths->traceroute_hops.size() == 0)
return;
/* XML traceroute header */
log_write(LOG_XML, "<trace ");
probe = currenths->traceroute_probespec;
if (probe.type == PS_TCP) {
log_write(LOG_XML, "port=\"%d\" ", probe.pd.tcp.dport);
} else if (probe.type == PS_UDP) {
log_write(LOG_XML, "port=\"%d\" ", probe.pd.udp.dport);
} else if (probe.type == PS_SCTP) {
log_write(LOG_XML, "port=\"%d\" ", probe.pd.sctp.dport);
} else if (probe.type == PS_ICMP || probe.type == PS_PROTO) {
struct protoent *proto = nmap_getprotbynum(htons(probe.proto));
if (proto == NULL)
log_write(LOG_XML, "proto=\"%d\"", probe.proto);
else
log_write(LOG_XML, "proto=\"%s\"", proto->p_name);
}
log_write(LOG_XML, ">\n");
for (it = currenths->traceroute_hops.begin();
it != currenths->traceroute_hops.end();
it++) {
if (it->timedout)
continue;
log_write(LOG_XML, "<hop ttl=\"%d\" rtt=\"%.2f\" ipaddr=\"%s\"",
it->ttl, it->rtt, inet_ntop_ez(&it->addr, sizeof(it->addr)));
if (!it->name.empty())
log_write(LOG_XML, " host=\"%s\"", it->name.c_str());
log_write(LOG_XML, "/>\n");
}
/*
if (tg->getState() == G_DEAD_TTL)
log_write(LOG_XML, "<error errorstr=\"maximum TTL reached\"/>\n");
else if (!tg->gotReply || (tp && (tp->ipreplysrc.s_addr != tg->ipdst)))
log_write(LOG_XML, "<error errorstr=\"destination not reached (%s)\"/>\n", inet_ntoa(tp->ipdst));
*/
/* traceroute XML footer */
log_write(LOG_XML, "</trace>\n");
log_flush(LOG_XML);
}
void printtraceroute(Target *currenths) {
printtraceroute_normal(currenths);
printtraceroute_xml(currenths);
}
/* Prints a status message while the program is running */ /* Prints a status message while the program is running */
void printStatusMessage() { void printStatusMessage() {
// Pre-computations // Pre-computations

View File

@@ -194,6 +194,9 @@ void printserviceinfooutput(Target *currenths);
void printhostscriptresults(Target *currenths); void printhostscriptresults(Target *currenths);
/* Print a table with traceroute hops. */
void printtraceroute(Target *currenths);
/* Print a detailed list of Nmap interfaces and routes to /* Print a detailed list of Nmap interfaces and routes to
normal/skiddy/stdout output */ normal/skiddy/stdout output */
int print_iflist(void); int print_iflist(void);

View File

@@ -1149,7 +1149,7 @@ void eth_close_cached() {
// fill ip header. no error check. // fill ip header. no error check.
// This function is also changing what's needed from host to network order. // This function is also changing what's needed from host to network order.
static inline int fill_ip_raw(struct ip *ip, int packetlen, u8 *ipopt, static inline int fill_ip_raw(struct ip *ip, int packetlen, const u8 *ipopt,
int ipoptlen, int ip_tos, int ip_id, int ipoptlen, int ip_tos, int ip_id,
int ip_off, int ip_ttl, int ip_p, int ip_off, int ip_ttl, int ip_p,
const struct in_addr *ip_src, const struct in_addr *ip_src,
@@ -1221,9 +1221,9 @@ int send_tcp_raw_decoys(int sd, struct eth_nfo *eth,
packetlen, which must be a valid int pointer. */ packetlen, which must be a valid int pointer. */
u8 *build_tcp_raw(const struct in_addr *source, u8 *build_tcp_raw(const struct in_addr *source,
const struct in_addr *victim, int ttl, u16 ipid, u8 tos, const struct in_addr *victim, int ttl, u16 ipid, u8 tos,
bool df, u8 *ipopt, int ipoptlen, u16 sport, u16 dport, bool df, const u8 *ipopt, int ipoptlen, u16 sport, u16 dport,
u32 seq, u32 ack, u8 reserved, u8 flags, u16 window, u32 seq, u32 ack, u8 reserved, u8 flags, u16 window,
u16 urp, u8 *tcpopt, int tcpoptlen, char *data, u16 urp, const u8 *tcpopt, int tcpoptlen, char *data,
u16 datalen, u32 *outpacketlen) { u16 datalen, u32 *outpacketlen) {
int packetlen = sizeof(struct ip) + ipoptlen + sizeof(struct tcp_hdr) + tcpoptlen + datalen; int packetlen = sizeof(struct ip) + ipoptlen + sizeof(struct tcp_hdr) + tcpoptlen + datalen;
u8 *packet = (u8 *) safe_malloc(packetlen); u8 *packet = (u8 *) safe_malloc(packetlen);
@@ -1792,11 +1792,11 @@ int send_udp_raw_decoys(int sd, struct eth_nfo *eth,
actually sent by this function. Caller must delete the buffer when actually sent by this function. Caller must delete the buffer when
finished with the packet. The packet length is returned in finished with the packet. The packet length is returned in
packetlen, which must be a valid int pointer. */ packetlen, which must be a valid int pointer. */
u8 *build_udp_raw(struct in_addr *source, const struct in_addr *victim, u8 *build_udp_raw(const struct in_addr *source, const struct in_addr *victim,
int ttl, u16 ipid, u8 tos, bool df, int ttl, u16 ipid, u8 tos, bool df,
u8 *ipopt, int ipoptlen, u8 *ipopt, int ipoptlen,
u16 sport, u16 dport, u16 sport, u16 dport,
char *data, u16 datalen, u32 *outpacketlen) { const char *data, u16 datalen, u32 *outpacketlen) {
int packetlen = int packetlen =
sizeof(struct ip) + ipoptlen + sizeof(struct udp_hdr) + datalen; sizeof(struct ip) + ipoptlen + sizeof(struct udp_hdr) + datalen;
u8 *packet = (u8 *) safe_malloc(packetlen); u8 *packet = (u8 *) safe_malloc(packetlen);

View File

@@ -505,10 +505,10 @@ int send_ip_raw( int sd, struct eth_nfo *eth,
packetlen, which must be a valid int pointer. */ packetlen, which must be a valid int pointer. */
u8 *build_tcp_raw(const struct in_addr *source, const struct in_addr *victim, u8 *build_tcp_raw(const struct in_addr *source, const struct in_addr *victim,
int ttl, u16 ipid, u8 tos, bool df, int ttl, u16 ipid, u8 tos, bool df,
u8* ipopt, int ipoptlen, const u8* ipopt, int ipoptlen,
u16 sport, u16 dport, u16 sport, u16 dport,
u32 seq, u32 ack, u8 reserved, u8 flags, u16 window, u16 urp, u32 seq, u32 ack, u8 reserved, u8 flags, u16 window, u16 urp,
u8 *options, int optlen, const u8 *options, int optlen,
char *data, u16 datalen, char *data, u16 datalen,
u32 *packetlen); u32 *packetlen);
@@ -518,11 +518,11 @@ u8 *build_tcp_raw(const struct in_addr *source, const struct in_addr *victim,
actually sent by this function. Caller must delete the buffer when actually sent by this function. Caller must delete the buffer when
finished with the packet. The packet length is returned in finished with the packet. The packet length is returned in
packetlen, which must be a valid int pointer. */ packetlen, which must be a valid int pointer. */
u8 *build_udp_raw(struct in_addr *source, const struct in_addr *victim, u8 *build_udp_raw(const struct in_addr *source, const struct in_addr *victim,
int ttl, u16 ipid, u8 tos, bool df, int ttl, u16 ipid, u8 tos, bool df,
u8* ipopt, int ipoptlen, u8* ipopt, int ipoptlen,
u16 sport, u16 dport, u16 sport, u16 dport,
char *data, u16 datalen, const char *data, u16 datalen,
u32 *packetlen); u32 *packetlen);
/* Builds an SCTP packet (including an IP header) by packing the fields /* Builds an SCTP packet (including an IP header) by packing the fields

File diff suppressed because it is too large Load Diff

View File

@@ -93,221 +93,6 @@
#include <vector> #include <vector>
/* Probe types */ int traceroute(std::vector<Target *> &Targets);
#define PROBE_TRACE 0
#define PROBE_TTL 1
/* Probe states */ void traceroute_hop_cache_clear();
#define P_TIMEDOUT 0 /* probe has timedout */
#define P_RETRANS 1 /* probe needs to be retransmitted */
#define P_OK 2 /* waiting for response or received response */
/* Group states */
#define G_OK P_OK
#define G_DEAD_TTL 3 /* TTL has reached maximum value */
#define G_FINISH 5 /* tracing has complete successfully */
#define MAX_TTL 50
#define HOP_COL 0
#define RTT_COL 1
#define HOST_COL 2
#define NAMEIPLEN MAXHOSTNAMELEN+INET6_ADDRSTRLEN
class NmapOutputTable;
/* Keeps track of each probes timing state */
class TimeInfo {
public:
TimeInfo();
int retranLimit();
void adjustTimeouts(struct timeval *recv, u16 scan_delay);
unsigned long probeTimeout() {
return MIN(10000000, to.timeout * 10);
}
/* true if this probe has been replied to */
u8 gotReply() {
return recvTime.tv_usec != 0 && recvTime.tv_sec != 0;
}
u8 getState() {
return state;
}
u8 setState(u8 state);
struct timeout_info to;
/* set to true if this probe is going to
* consolidated because it has timed out */
bool consolidated;
/* Rtt and timeout calculation */
struct timeval recvTime;
struct timeval sendTime;
private:
u8 retransmissions;
u8 state;
};
/* traceprobes represent a single packet at a specific ttl. Traceprobes are
* stored inside tracegroups. */
class TraceProbe {
public:
TraceProbe(u32 dip, u32 sip, u16 sport, struct probespec& probe);
~TraceProbe();
/* Return the ip address and resolved hostname in a string such as
* "host.com (1.2.3.4)" or "6.6.6.6". */
const char *nameIP();
const char *HostName() {
if (!hostname || !(*hostname))
return NULL;
else
return *hostname;
}
/* probe type is either a standard probe (PROBE_TRACE) or a hop distance
* probe (PROBE_TTL) */
void setProbeType(u8 type) {
this->probetype = type;
}
u8 probeType() {
return probetype;
}
char *ipReplyStr() {
return inet_ntoa (ipreplysrc);
}
/* protocol information for this probe */
TimeInfo timing;
struct in_addr ipdst;
struct in_addr ipsrc;
struct in_addr ipreplysrc;
struct probespec probe;
u16 sport;
u8 ttl;
char **hostname;
private:
u8 probetype;
char *hostnameip;
};
/* each trace group represents a target ip and contains a map of probes that
* have been sent/recv'ed to/from the ip */
class TraceGroup {
public:
TraceGroup(u32 dip, u16 sport, struct probespec& probe);
~TraceGroup();
/* map of all probes sent to this TraceGroups IP address. The map is keyed
* by the source port number of the probe */
std::map < u16, TraceProbe * >TraceProbes;
std::map < u16, TraceProbe * >::size_type size() {
return TraceProbes.size ();
}
/* checks for timedout probes and retransmits them Any probe that exceeds
* the timing limits is considered non-responsive */
void retransmissions(std::vector < TraceProbe * >&retrans);
/* Returns a map from TTLs to probes, stripped of all unneeded probes and
* with timed-out probes marked for consolidation. */
std::map < u8, TraceProbe * > consolidateHops() const;
/* the next ttl to send, if the destination has replied the ttl is
* decremented, if it hasn't it is incremented */
void nextTTL();
/* number of probes currently waiting for replies */
void incRemaining();
void decRemaining();
char *IPStr();
u8 getRemaining() {
return remaining;
}
u8 getState() {
return state;
}
u8 setState(u8 state);
u8 setHopDistance(u8 hop_distance, u8 ttl);
/* Get the number of hops to the target, or -1 if unknown. Use this instead
* of reading hopDistance, which despite its name does not contain the final
* hop count. */
int getDistance();
bool gotReply;
bool noDistProbe;
/* Group wide timing */
int scanDelay;
int maxRetransmissions;
u16 droppedPackets;
u16 repliedPackets;
u8 consecTimeouts;
/* protocol information */
struct probespec probe;
u16 sport;
u32 ipdst;
/* estimated ttl distance to target */
u8 hopDistance;
/* largest ttl send so far */
u8 ttl;
/* the initial ttl guess. This is needed because the ttl may have to be
* incremented to reach the destination host. Once nmap has reached the
* destination it needs to start decrementing the ttl from the original
* value so no duplicate probes are sent.
*
* For example, if the guess is 20 but the target is at 23. We will start
* tracing backwards at 19. */
u8 start_ttl;
u8 consolidation_start;
const u8 *src_mac_addr;
const u8 *nxt_mac_addr;
private:
/* the number of probes sent but and not yet replied to */
u8 remaining;
/* default state is G_OK, set to G_FINISH when
* complete or one of the G_* error codes if this
* group fails */
u8 state;
};
/* Public interface to traceroute functionality */
class Traceroute {
public:
Traceroute(const char *device_name, devtype type, const scan_lists * probe_ports);
~Traceroute();
/* perform the traceroute on a list of targets */
void trace(std::vector < Target * >&Targets);
/* Use nmaps rDNS functions to mass resolve the hops ip addresses */
void resolveHops();
/* display plain and XML traceroutes for target t */
void outputTarget(Target * t);
private:
/* map of all TraceGroups, keyed by
* the groups destination IP address */
std::map < u32, TraceGroup * >TraceGroups;
const struct scan_lists * scanlists;
Target **hops;
pcap_t *pd;
eth_t *ethsd;
int fd, total_size, cp_flag;
struct in_addr ref_ipaddr;
/* called by outputTarget to log XML data */
void outputXMLTrace(TraceGroup * tg);
/* find a responsive port for t based on scan results */
const probespec getTraceProbe(Target * t);
/* sendTTLProbes() guesses the hop distance to a target by actively probing
* the host. */
void sendTTLProbes(std::vector < Target * >&Targets, std::vector < Target * >&vaild_targets);
int sendProbe(TraceProbe * tp);
/* reads probe replies for all protocols. returns finished(), which returns
* true when all groups have finished or failed */
bool readTraceResponses();
bool finished();
/* add message to output table "hops 1 to X are the same as <reference ip>".
* This message should always come before none-consolidated hop output */
void addConsolidationMessage(NmapOutputTable *Tbl, unsigned short row_count, unsigned short ttl);
};