mirror of
https://github.com/nmap/nmap.git
synced 2025-12-16 04:39:03 +00:00
make a ton of global symbols static
This commit is contained in:
10
CHANGELOG
10
CHANGELOG
@@ -1,4 +1,14 @@
|
||||
# Nmap Changelog ($Id$); -*-text-*-
|
||||
o Made some changes to various Nmap initialization functions which
|
||||
help ALT Linux (altlinux.org) developers run Nmap in a chroot
|
||||
environment. Thanks to Dmitry V. Levin (ldv(a)altlinux.org) for the
|
||||
patch.
|
||||
|
||||
o Cleaned up the code a bit by making a bunch (nearly 100) global
|
||||
symols (mostly function calls) static. I was also able to removed
|
||||
some unused functions. Thanks to Dmitry V. Levin (ldv(a)altlinux.org)
|
||||
for sending a list of candidate symbols.
|
||||
|
||||
Nmap 4.02ALPHA1
|
||||
|
||||
o Added the --log-errors option, which causes most warnings and error
|
||||
|
||||
11
MACLookup.cc
11
MACLookup.cc
@@ -117,8 +117,6 @@ struct MAC_hash_table {
|
||||
struct MAC_entry **table;
|
||||
} MacTable;
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
static inline int MacCharPrefix2Key(const u8 *prefix) {
|
||||
return (prefix[0] << 16) + (prefix[1] << 8) + prefix[2];
|
||||
}
|
||||
@@ -130,7 +128,8 @@ static inline int MACTableHash(int prefix, int table_capacity) {
|
||||
return prefix % table_capacity;
|
||||
}
|
||||
|
||||
void InitializeTable() {
|
||||
void mac_prefix_init() {
|
||||
static int initialized = 0;
|
||||
if (initialized) return;
|
||||
initialized = 1;
|
||||
char filename[256];
|
||||
@@ -196,7 +195,7 @@ void InitializeTable() {
|
||||
}
|
||||
|
||||
|
||||
struct MAC_entry *findMACEntry(int prefix) {
|
||||
static struct MAC_entry *findMACEntry(int prefix) {
|
||||
int pos = MACTableHash(prefix, MacTable.table_capacity);
|
||||
|
||||
while (MacTable.table[pos]) {
|
||||
@@ -216,7 +215,7 @@ const char *MACPrefix2Corp(const u8 *prefix) {
|
||||
struct MAC_entry *ent;
|
||||
|
||||
if (!prefix) fatal("MACPrefix2Corp called with a NULL prefix");
|
||||
if (!initialized) InitializeTable();
|
||||
mac_prefix_init();
|
||||
|
||||
ent = findMACEntry(MacCharPrefix2Key(prefix));
|
||||
return (ent)? ent->vendor : NULL;
|
||||
@@ -231,7 +230,7 @@ const char *MACPrefix2Corp(const u8 *prefix) {
|
||||
bool MACCorp2Prefix(const char *vendorstr, u8 *mac_data) {
|
||||
if (!vendorstr) fatal("%s: vendorstr is NULL", __FUNCTION__);
|
||||
if (!mac_data) fatal("%s: mac_data is NULL", __FUNCTION__);
|
||||
if (!initialized) InitializeTable();
|
||||
mac_prefix_init();
|
||||
|
||||
for(int i = 0; i < MacTable.table_capacity; i++ ) {
|
||||
if (MacTable.table[i])
|
||||
|
||||
@@ -107,11 +107,13 @@ static char *charpool[16];
|
||||
static int currentcharpool;
|
||||
static int currentcharpoolsz;
|
||||
static char *nextchar;
|
||||
static int charpool_initialized = 0;
|
||||
|
||||
#define ALIGN_ON sizeof(char *)
|
||||
|
||||
static int cp_init(void) {
|
||||
static int charpool_initialized = 0;
|
||||
if (charpool_initialized) return 0;
|
||||
|
||||
/* Create our char pool */
|
||||
currentcharpool = 0;
|
||||
currentcharpoolsz = 16384;
|
||||
@@ -135,7 +137,7 @@ void *cp_alloc(int sz) {
|
||||
char *p;
|
||||
int modulus;
|
||||
|
||||
if (!charpool_initialized) cp_init();
|
||||
cp_init();
|
||||
|
||||
if ((modulus = sz % ALIGN_ON))
|
||||
sz += ALIGN_ON - modulus;
|
||||
@@ -159,7 +161,6 @@ char *q;
|
||||
char *end;
|
||||
int modulus;
|
||||
|
||||
if (!charpool_initialized)
|
||||
cp_init();
|
||||
|
||||
end = charpool[currentcharpool] + currentcharpoolsz;
|
||||
|
||||
16
idle_scan.cc
16
idle_scan.cc
@@ -154,7 +154,7 @@ struct idle_proxy_info {
|
||||
Proxy timing is adjusted, but proxy->latestid is NOT ADJUSTED --
|
||||
you'll have to do that yourself. Probes_sent is set to the number
|
||||
of probe packets sent during execution */
|
||||
int ipid_proxy_probe(struct idle_proxy_info *proxy, int *probes_sent,
|
||||
static int ipid_proxy_probe(struct idle_proxy_info *proxy, int *probes_sent,
|
||||
int *probes_rcvd) {
|
||||
struct timeval tv_end;
|
||||
int tries = 0;
|
||||
@@ -248,7 +248,7 @@ int ipid_proxy_probe(struct idle_proxy_info *proxy, int *probes_sent,
|
||||
one, assuming the given IPID Sequencing class. Returns -1 if the
|
||||
distance cannot be determined */
|
||||
|
||||
int ipid_distance(int seqclass , u16 startid, u16 endid) {
|
||||
static int ipid_distance(int seqclass , u16 startid, u16 endid) {
|
||||
if (seqclass == IPID_SEQ_INCR)
|
||||
return endid - startid;
|
||||
|
||||
@@ -279,7 +279,7 @@ static void initialize_proxy_struct(struct idle_proxy_info *proxy) {
|
||||
proxy is determined to be unsuitable, the function whines and exits
|
||||
the program */
|
||||
#define NUM_IPID_PROBES 6
|
||||
void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
|
||||
static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
|
||||
const struct in_addr *first_target) {
|
||||
int probes_sent = 0, probes_returned = 0;
|
||||
int hardtimeout = 9000000; /* Generally don't wait more than 9 secs total */
|
||||
@@ -378,7 +378,7 @@ void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
|
||||
proxy->ethptr = &proxy->eth;
|
||||
} else {
|
||||
if ((proxy->rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )
|
||||
pfatal("socket trobles in get_fingerprint");
|
||||
pfatal("socket trobles in %s", __FUNCTION__);
|
||||
unblock_socket(proxy->rawsd);
|
||||
broadcast_socket(proxy->rawsd);
|
||||
#ifndef WIN32
|
||||
@@ -560,7 +560,7 @@ void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
|
||||
count of 'testcount' while the 'realcount' is as given. If the
|
||||
testcount was correct, timing is made more aggressive, while it is
|
||||
slowed down in the case of an error */
|
||||
void adjust_idle_timing(struct idle_proxy_info *proxy,
|
||||
static void adjust_idle_timing(struct idle_proxy_info *proxy,
|
||||
Target *target, int testcount,
|
||||
int realcount) {
|
||||
|
||||
@@ -622,7 +622,7 @@ void adjust_idle_timing(struct idle_proxy_info *proxy,
|
||||
They can be NULL if you don't want to use them. The purpose is for
|
||||
timing adjustments if the numbers turn out to be accurate */
|
||||
|
||||
int idlescan_countopen2(struct idle_proxy_info *proxy,
|
||||
static int idlescan_countopen2(struct idle_proxy_info *proxy,
|
||||
Target *target, u16 *ports, int numports,
|
||||
struct timeval *sent_time, struct timeval *rcv_time)
|
||||
{
|
||||
@@ -777,7 +777,7 @@ int idlescan_countopen2(struct idle_proxy_info *proxy,
|
||||
/* The job of this function is to use the Idlescan technique to count
|
||||
the number of open ports in the given list. Under the covers, this
|
||||
function just farms out the hard work to another function */
|
||||
int idlescan_countopen(struct idle_proxy_info *proxy,
|
||||
static int idlescan_countopen(struct idle_proxy_info *proxy,
|
||||
Target *target, u16 *ports, int numports,
|
||||
struct timeval *sent_time, struct timeval *rcv_time) {
|
||||
int tries = 0;
|
||||
@@ -818,7 +818,7 @@ int idlescan_countopen(struct idle_proxy_info *proxy,
|
||||
/* Recursively Idlescans scans a group of ports using a depth-first
|
||||
divide-and-conquer strategy to find the open one(s) */
|
||||
|
||||
int idle_treescan(struct idle_proxy_info *proxy, Target *target,
|
||||
static int idle_treescan(struct idle_proxy_info *proxy, Target *target,
|
||||
u16 *ports, int numports, int expectedopen) {
|
||||
|
||||
int firstHalfSz = (numports + 1)/2;
|
||||
|
||||
481
nmap.cc
481
nmap.cc
@@ -192,6 +192,240 @@ static int parse_bounce_argument(struct ftpinfo *ftp, char *url) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void printusage(char *name, int rc) {
|
||||
|
||||
printf("%s %s ( %s )\n"
|
||||
"Usage: nmap [Scan Type(s)] [Options] {target specification}\n"
|
||||
"TARGET SPECIFICATION:\n"
|
||||
" Can pass hostnames, IP addresses, networks, etc.\n"
|
||||
" Ex: scanme.nmap.org, microsoft.com/24, 192.168.0.1; 10.0.0-255.1-254\n"
|
||||
" -iL <inputfilename>: Input from list of hosts/networks\n"
|
||||
" -iR <num hosts>: Choose random targets\n"
|
||||
" --exclude <host1[,host2][,host3],...>: Exclude hosts/networks\n"
|
||||
" --excludefile <exclude_file>: Exclude list from file\n"
|
||||
"HOST DISCOVERY:\n"
|
||||
" -sL: List Scan - simply list targets to scan\n"
|
||||
" -sP: Ping Scan - go no further than determining if host is online\n"
|
||||
" -P0: Treat all hosts as online -- skip host discovery\n"
|
||||
" -PS/PA/PU [portlist]: TCP SYN/ACK or UDP discovery to given ports\n"
|
||||
" -PE/PP/PM: ICMP echo, timestamp, and netmask request discovery probes\n"
|
||||
" -n/-R: Never do DNS resolution/Always resolve [default: sometimes]\n"
|
||||
" --dns-servers <serv1[,serv2],...>: Specify custom DNS servers\n"
|
||||
" --system-dns: Use OS's DNS resolver\n"
|
||||
"SCAN TECHNIQUES:\n"
|
||||
" -sS/sT/sA/sW/sM: TCP SYN/Connect()/ACK/Window/Maimon scans\n"
|
||||
" -sN/sF/sX: TCP Null, FIN, and Xmas scans\n"
|
||||
" --scanflags <flags>: Customize TCP scan flags\n"
|
||||
" -sI <zombie host[:probeport]>: Idlescan\n"
|
||||
" -sO: IP protocol scan\n"
|
||||
" -b <ftp relay host>: FTP bounce scan\n"
|
||||
"PORT SPECIFICATION AND SCAN ORDER:\n"
|
||||
" -p <port ranges>: Only scan specified ports\n"
|
||||
" Ex: -p22; -p1-65535; -p U:53,111,137,T:21-25,80,139,8080\n"
|
||||
" -F: Fast - Scan only the ports listed in the nmap-services file)\n"
|
||||
" -r: Scan ports consecutively - don't randomize\n"
|
||||
"SERVICE/VERSION DETECTION:\n"
|
||||
" -sV: Probe open ports to determine service/version info\n"
|
||||
" --version-intensity <level>: Set from 0 (light) to 9 (try all probes)\n"
|
||||
" --version-light: Limit to most likely probes (intensity 2)\n"
|
||||
" --version-all: Try every single probe (intensity 9)\n"
|
||||
" --version-trace: Show detailed version scan activity (for debugging)\n"
|
||||
"OS DETECTION:\n"
|
||||
" -O: Enable OS detection\n"
|
||||
" --osscan-limit: Limit OS detection to promising targets\n"
|
||||
" --osscan-guess: Guess OS more aggressively\n"
|
||||
"TIMING AND PERFORMANCE:\n"
|
||||
" Options which take <time> are in milliseconds, unless you append 's'\n"
|
||||
" (seconds), 'm' (minutes), or 'h' (hours) to the value (e.g. 30m).\n"
|
||||
" -T[0-5]: Set timing template (higher is faster)\n"
|
||||
" --min-hostgroup/max-hostgroup <size>: Parallel host scan group sizes\n"
|
||||
" --min-parallelism/max-parallelism <time>: Probe parallelization\n"
|
||||
" --min-rtt-timeout/max-rtt-timeout/initial-rtt-timeout <time>: Specifies\n"
|
||||
" probe round trip time.\n"
|
||||
" --max-retries <tries>: Caps number of port scan probe retransmissions.\n"
|
||||
" --host-timeout <time>: Give up on target after this long\n"
|
||||
" --scan-delay/--max-scan-delay <time>: Adjust delay between probes\n"
|
||||
"FIREWALL/IDS EVASION AND SPOOFING:\n"
|
||||
" -f; --mtu <val>: fragment packets (optionally w/given MTU)\n"
|
||||
" -D <decoy1,decoy2[,ME],...>: Cloak a scan with decoys\n"
|
||||
" -S <IP_Address>: Spoof source address\n"
|
||||
" -e <iface>: Use specified interface\n"
|
||||
" -g/--source-port <portnum>: Use given port number\n"
|
||||
" --data-length <num>: Append random data to sent packets\n"
|
||||
" --ttl <val>: Set IP time-to-live field\n"
|
||||
" --spoof-mac <mac address/prefix/vendor name>: Spoof your MAC address\n"
|
||||
" --badsum: Send packets with a bogus TCP/UDP checksum\n"
|
||||
"OUTPUT:\n"
|
||||
" -oN/-oX/-oS/-oG <file>: Output scan in normal, XML, s|<rIpt kIddi3,\n"
|
||||
" and Grepable format, respectively, to the given filename.\n"
|
||||
" -oA <basename>: Output in the three major formats at once\n"
|
||||
" -v: Increase verbosity level (use twice for more effect)\n"
|
||||
" -d[level]: Set or increase debugging level (Up to 9 is meaningful)\n"
|
||||
" --packet-trace: Show all packets sent and received\n"
|
||||
" --iflist: Print host interfaces and routes (for debugging)\n"
|
||||
" --log-errors: Log errors/warnings to the normal-format output file\n"
|
||||
" --append-output: Append to rather than clobber specified output files\n"
|
||||
" --resume <filename>: Resume an aborted scan\n"
|
||||
" --stylesheet <path/URL>: XSL stylesheet to transform XML output to HTML\n"
|
||||
" --webxml: Reference stylesheet from Insecure.Org for more portable XML\n"
|
||||
" --no-stylesheet: Prevent associating of XSL stylesheet w/XML output\n"
|
||||
"MISC:\n"
|
||||
" -6: Enable IPv6 scanning\n"
|
||||
" -A: Enables OS detection and Version detection\n"
|
||||
" --datadir <dirname>: Specify custom Nmap data file location\n"
|
||||
" --send-eth/--send-ip: Send using raw ethernet frames or IP packets\n"
|
||||
" --privileged: Assume that the user is fully privileged\n"
|
||||
" -V: Print version number\n"
|
||||
" -h: Print this help summary page.\n"
|
||||
"EXAMPLES:\n"
|
||||
" nmap -v -A scanme.nmap.org\n"
|
||||
" nmap -v -sP 192.168.0.0/16 10.0.0.0/8\n"
|
||||
" nmap -v -iR 10000 -P0 -p 80\n"
|
||||
"SEE THE MAN PAGE FOR MANY MORE OPTIONS, DESCRIPTIONS, AND EXAMPLES\n", NMAP_NAME, NMAP_VERSION, NMAP_URL);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 1 if this is a reserved IP address, where "reserved" means
|
||||
* either a private address, non-routable address, or even a non-reserved
|
||||
* but unassigned address which has an extremely high probability of being
|
||||
* black-holed.
|
||||
*
|
||||
* We try to optimize speed when ordering the tests. This optimization
|
||||
* assumes that all byte values are equally likely in the input.
|
||||
*
|
||||
* Warning: This function could easily become outdated if the IANA
|
||||
* starts to assign some more IPv4 ranges to RIPE, etc. as they have
|
||||
* started doing this year (2001), for example 80.0.0.0/4 used to be
|
||||
* completely unassigned until they gave 80.0.0.0/7 to RIPE in April
|
||||
* 2001 (www.junk.org is an example of a new address in this range).
|
||||
*
|
||||
* Check <http://www.iana.org/assignments/ipv4-address-space> for
|
||||
* the most recent assigments and
|
||||
* <http://www.cymru.com/Documents/bogon-bn-nonagg.txt> for bogon
|
||||
* netblocks.
|
||||
*/
|
||||
static int ip_is_reserved(struct in_addr *ip)
|
||||
{
|
||||
char *ipc = (char *) &(ip->s_addr);
|
||||
unsigned char i1 = ipc[0], i2 = ipc[1], i3 = ipc[2], i4 = ipc[3];
|
||||
|
||||
/* do all the /7's and /8's with a big switch statement, hopefully the
|
||||
* compiler will be able to optimize this a little better using a jump table
|
||||
* or what have you
|
||||
*/
|
||||
switch (i1)
|
||||
{
|
||||
case 0: /* 000/8 is IANA reserved */
|
||||
case 1: /* 001/8 is IANA reserved */
|
||||
case 2: /* 002/8 is IANA reserved */
|
||||
case 5: /* 005/8 is IANA reserved */
|
||||
case 6: /* USA Army ISC */
|
||||
case 7: /* used for BGP protocol */
|
||||
case 10: /* the infamous 10.0.0.0/8 */
|
||||
case 23: /* 023/8 is IANA reserved */
|
||||
case 27: /* 027/8 is IANA reserved */
|
||||
case 31: /* 031/8 is IANA reserved */
|
||||
case 36: /* 036/8 is IANA reserved */
|
||||
case 37: /* 037/8 is IANA reserved */
|
||||
case 39: /* 039/8 is IANA reserved */
|
||||
case 42: /* 042/8 is IANA reserved */
|
||||
case 49: /* 049/8 is IANA reserved */
|
||||
case 50: /* 050/8 is IANA reserved */
|
||||
case 55: /* misc. U.S.A. Armed forces */
|
||||
case 127: /* 127/8 is reserved for loopback */
|
||||
case 197: /* 197/8 is IANA reserved */
|
||||
case 223: /* 223/8 is IANA reserved */
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* 077-079/8 is IANA reserved */
|
||||
if (i1 >= 77 && i1 <= 79)
|
||||
return 1;
|
||||
|
||||
/* 092-123/8 is IANA reserved */
|
||||
if (i1 >= 92 && i1 <= 123)
|
||||
return 1;
|
||||
|
||||
/* 172.16.0.0/12 is reserved for private nets by RFC1819 */
|
||||
if (i1 == 172 && i2 >= 16 && i2 <= 31)
|
||||
return 1;
|
||||
|
||||
/* 173-187/8 is IANA reserved */
|
||||
if (i1 >= 173 && i1 <= 187)
|
||||
return 1;
|
||||
|
||||
/* 192.168.0.0/16 is reserved for private nets by RFC1819 */
|
||||
/* 192.0.2.0/24 is reserved for documentation and examples */
|
||||
/* 192.88.99.0/24 is used as 6to4 Relay anycast prefix by RFC3068 */
|
||||
if (i1 == 192) {
|
||||
if (i2 == 168)
|
||||
return 1;
|
||||
if (i2 == 0 && i3 == 2)
|
||||
return 1;
|
||||
if (i2 == 88 && i3 == 99)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 198.18.0.0/15 is used for benchmark tests by RFC2544 */
|
||||
if (i1 == 198 && i2 == 18 && i3 >= 1 && i3 <= 64) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* reserved for DHCP clients seeking addresses, not routable outside LAN */
|
||||
if (i1 == 169 && i2 == 254)
|
||||
return 1;
|
||||
|
||||
/* believe it or not, 204.152.64.0/23 is some bizarre Sun proprietary
|
||||
* clustering thing */
|
||||
if (i1 == 204 && i2 == 152 && (i3 == 64 || i3 == 65))
|
||||
return 1;
|
||||
|
||||
/* 224-239/8 is all multicast stuff */
|
||||
/* 240-255/8 is IANA reserved */
|
||||
if (i1 >= 224)
|
||||
return 1;
|
||||
|
||||
/* 255.255.255.255, note we already tested for i1 in this range */
|
||||
if (i2 == 255 && i3 == 255 && i4 == 255)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *grab_next_host_spec(FILE *inputfd, int argc, char **fakeargv) {
|
||||
static char host_spec[1024];
|
||||
unsigned int host_spec_index;
|
||||
int ch;
|
||||
struct in_addr ip;
|
||||
|
||||
if (o.generate_random_ips) {
|
||||
do {
|
||||
ip.s_addr = get_random_u32();
|
||||
} while (ip_is_reserved(&ip));
|
||||
Strncpy(host_spec, inet_ntoa(ip), sizeof(host_spec));
|
||||
} else if (!inputfd) {
|
||||
return( (optind < argc)? fakeargv[optind++] : NULL);
|
||||
} else {
|
||||
host_spec_index = 0;
|
||||
while((ch = getc(inputfd)) != EOF) {
|
||||
if (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t' || ch == '\0') {
|
||||
if (host_spec_index == 0) continue;
|
||||
host_spec[host_spec_index] = '\0';
|
||||
return host_spec;
|
||||
} else if (host_spec_index < sizeof(host_spec) / sizeof(char) -1) {
|
||||
host_spec[host_spec_index++] = (char) ch;
|
||||
} else fatal("One of the host_specifications from your input file is too long (> %d chars)", (int) sizeof(host_spec));
|
||||
}
|
||||
host_spec[host_spec_index] = '\0';
|
||||
}
|
||||
if (!*host_spec) return NULL;
|
||||
return host_spec;
|
||||
}
|
||||
|
||||
int nmap_main(int argc, char *argv[]) {
|
||||
char *p, *q;
|
||||
int i, arg;
|
||||
@@ -1629,98 +1863,6 @@ struct scan_lists *getpts(char *origexpr) {
|
||||
return ports;
|
||||
}
|
||||
|
||||
void printusage(char *name, int rc) {
|
||||
|
||||
printf("%s %s ( %s )\n"
|
||||
"Usage: nmap [Scan Type(s)] [Options] {target specification}\n"
|
||||
"TARGET SPECIFICATION:\n"
|
||||
" Can pass hostnames, IP addresses, networks, etc.\n"
|
||||
" Ex: scanme.nmap.org, microsoft.com/24, 192.168.0.1; 10.0.0-255.1-254\n"
|
||||
" -iL <inputfilename>: Input from list of hosts/networks\n"
|
||||
" -iR <num hosts>: Choose random targets\n"
|
||||
" --exclude <host1[,host2][,host3],...>: Exclude hosts/networks\n"
|
||||
" --excludefile <exclude_file>: Exclude list from file\n"
|
||||
"HOST DISCOVERY:\n"
|
||||
" -sL: List Scan - simply list targets to scan\n"
|
||||
" -sP: Ping Scan - go no further than determining if host is online\n"
|
||||
" -P0: Treat all hosts as online -- skip host discovery\n"
|
||||
" -PS/PA/PU [portlist]: TCP SYN/ACK or UDP discovery to given ports\n"
|
||||
" -PE/PP/PM: ICMP echo, timestamp, and netmask request discovery probes\n"
|
||||
" -n/-R: Never do DNS resolution/Always resolve [default: sometimes]\n"
|
||||
" --dns-servers <serv1[,serv2],...>: Specify custom DNS servers\n"
|
||||
" --system-dns: Use OS's DNS resolver\n"
|
||||
"SCAN TECHNIQUES:\n"
|
||||
" -sS/sT/sA/sW/sM: TCP SYN/Connect()/ACK/Window/Maimon scans\n"
|
||||
" -sN/sF/sX: TCP Null, FIN, and Xmas scans\n"
|
||||
" --scanflags <flags>: Customize TCP scan flags\n"
|
||||
" -sI <zombie host[:probeport]>: Idlescan\n"
|
||||
" -sO: IP protocol scan\n"
|
||||
" -b <ftp relay host>: FTP bounce scan\n"
|
||||
"PORT SPECIFICATION AND SCAN ORDER:\n"
|
||||
" -p <port ranges>: Only scan specified ports\n"
|
||||
" Ex: -p22; -p1-65535; -p U:53,111,137,T:21-25,80,139,8080\n"
|
||||
" -F: Fast - Scan only the ports listed in the nmap-services file)\n"
|
||||
" -r: Scan ports consecutively - don't randomize\n"
|
||||
"SERVICE/VERSION DETECTION:\n"
|
||||
" -sV: Probe open ports to determine service/version info\n"
|
||||
" --version-intensity <level>: Set from 0 (light) to 9 (try all probes)\n"
|
||||
" --version-light: Limit to most likely probes (intensity 2)\n"
|
||||
" --version-all: Try every single probe (intensity 9)\n"
|
||||
" --version-trace: Show detailed version scan activity (for debugging)\n"
|
||||
"OS DETECTION:\n"
|
||||
" -O: Enable OS detection\n"
|
||||
" --osscan-limit: Limit OS detection to promising targets\n"
|
||||
" --osscan-guess: Guess OS more aggressively\n"
|
||||
"TIMING AND PERFORMANCE:\n"
|
||||
" Options which take <time> are in milliseconds, unless you append 's'\n"
|
||||
" (seconds), 'm' (minutes), or 'h' (hours) to the value (e.g. 30m).\n"
|
||||
" -T[0-5]: Set timing template (higher is faster)\n"
|
||||
" --min-hostgroup/max-hostgroup <size>: Parallel host scan group sizes\n"
|
||||
" --min-parallelism/max-parallelism <time>: Probe parallelization\n"
|
||||
" --min-rtt-timeout/max-rtt-timeout/initial-rtt-timeout <time>: Specifies\n"
|
||||
" probe round trip time.\n"
|
||||
" --max-retries <tries>: Caps number of port scan probe retransmissions.\n"
|
||||
" --host-timeout <time>: Give up on target after this long\n"
|
||||
" --scan-delay/--max-scan-delay <time>: Adjust delay between probes\n"
|
||||
"FIREWALL/IDS EVASION AND SPOOFING:\n"
|
||||
" -f; --mtu <val>: fragment packets (optionally w/given MTU)\n"
|
||||
" -D <decoy1,decoy2[,ME],...>: Cloak a scan with decoys\n"
|
||||
" -S <IP_Address>: Spoof source address\n"
|
||||
" -e <iface>: Use specified interface\n"
|
||||
" -g/--source-port <portnum>: Use given port number\n"
|
||||
" --data-length <num>: Append random data to sent packets\n"
|
||||
" --ttl <val>: Set IP time-to-live field\n"
|
||||
" --spoof-mac <mac address/prefix/vendor name>: Spoof your MAC address\n"
|
||||
" --badsum: Send packets with a bogus TCP/UDP checksum\n"
|
||||
"OUTPUT:\n"
|
||||
" -oN/-oX/-oS/-oG <file>: Output scan in normal, XML, s|<rIpt kIddi3,\n"
|
||||
" and Grepable format, respectively, to the given filename.\n"
|
||||
" -oA <basename>: Output in the three major formats at once\n"
|
||||
" -v: Increase verbosity level (use twice for more effect)\n"
|
||||
" -d[level]: Set or increase debugging level (Up to 9 is meaningful)\n"
|
||||
" --packet-trace: Show all packets sent and received\n"
|
||||
" --iflist: Print host interfaces and routes (for debugging)\n"
|
||||
" --log-errors: Log errors/warnings to the normal-format output file\n"
|
||||
" --append-output: Append to rather than clobber specified output files\n"
|
||||
" --resume <filename>: Resume an aborted scan\n"
|
||||
" --stylesheet <path/URL>: XSL stylesheet to transform XML output to HTML\n"
|
||||
" --webxml: Reference stylesheet from Insecure.Org for more portable XML\n"
|
||||
" --no-stylesheet: Prevent associating of XSL stylesheet w/XML output\n"
|
||||
"MISC:\n"
|
||||
" -6: Enable IPv6 scanning\n"
|
||||
" -A: Enables OS detection and Version detection\n"
|
||||
" --datadir <dirname>: Specify custom Nmap data file location\n"
|
||||
" --send-eth/--send-ip: Send using raw ethernet frames or IP packets\n"
|
||||
" --privileged: Assume that the user is fully privileged\n"
|
||||
" -V: Print version number\n"
|
||||
" -h: Print this help summary page.\n"
|
||||
"EXAMPLES:\n"
|
||||
" nmap -v -A scanme.nmap.org\n"
|
||||
" nmap -v -sP 192.168.0.0/16 10.0.0.0/8\n"
|
||||
" nmap -v -iR 10000 -P0 -p 80\n"
|
||||
"SEE THE MAN PAGE FOR MANY MORE OPTIONS, DESCRIPTIONS, AND EXAMPLES\n", NMAP_NAME, NMAP_VERSION, NMAP_URL);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
void printinteractiveusage() {
|
||||
printf(
|
||||
@@ -1819,148 +1961,7 @@ char *tsseqclass2ascii(int seqclass) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns 1 if this is a reserved IP address, where "reserved" means
|
||||
* either a private address, non-routable address, or even a non-reserved
|
||||
* but unassigned address which has an extremely high probability of being
|
||||
* black-holed.
|
||||
*
|
||||
* We try to optimize speed when ordering the tests. This optimization
|
||||
* assumes that all byte values are equally likely in the input.
|
||||
*
|
||||
* Warning: This function could easily become outdated if the IANA
|
||||
* starts to assign some more IPv4 ranges to RIPE, etc. as they have
|
||||
* started doing this year (2001), for example 80.0.0.0/4 used to be
|
||||
* completely unassigned until they gave 80.0.0.0/7 to RIPE in April
|
||||
* 2001 (www.junk.org is an example of a new address in this range).
|
||||
*
|
||||
* Check <http://www.iana.org/assignments/ipv4-address-space> for
|
||||
* the most recent assigments and
|
||||
* <http://www.cymru.com/Documents/bogon-bn-nonagg.txt> for bogon
|
||||
* netblocks.
|
||||
*/
|
||||
|
||||
int ip_is_reserved(struct in_addr *ip)
|
||||
{
|
||||
char *ipc = (char *) &(ip->s_addr);
|
||||
unsigned char i1 = ipc[0], i2 = ipc[1], i3 = ipc[2], i4 = ipc[3];
|
||||
|
||||
/* do all the /7's and /8's with a big switch statement, hopefully the
|
||||
* compiler will be able to optimize this a little better using a jump table
|
||||
* or what have you
|
||||
*/
|
||||
switch (i1)
|
||||
{
|
||||
case 0: /* 000/8 is IANA reserved */
|
||||
case 1: /* 001/8 is IANA reserved */
|
||||
case 2: /* 002/8 is IANA reserved */
|
||||
case 5: /* 005/8 is IANA reserved */
|
||||
case 6: /* USA Army ISC */
|
||||
case 7: /* used for BGP protocol */
|
||||
case 10: /* the infamous 10.0.0.0/8 */
|
||||
case 23: /* 023/8 is IANA reserved */
|
||||
case 27: /* 027/8 is IANA reserved */
|
||||
case 31: /* 031/8 is IANA reserved */
|
||||
case 36: /* 036/8 is IANA reserved */
|
||||
case 37: /* 037/8 is IANA reserved */
|
||||
case 39: /* 039/8 is IANA reserved */
|
||||
case 42: /* 042/8 is IANA reserved */
|
||||
case 49: /* 049/8 is IANA reserved */
|
||||
case 50: /* 050/8 is IANA reserved */
|
||||
case 55: /* misc. U.S.A. Armed forces */
|
||||
case 127: /* 127/8 is reserved for loopback */
|
||||
case 197: /* 197/8 is IANA reserved */
|
||||
case 223: /* 223/8 is IANA reserved */
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* 077-079/8 is IANA reserved */
|
||||
if (i1 >= 77 && i1 <= 79)
|
||||
return 1;
|
||||
|
||||
/* 092-123/8 is IANA reserved */
|
||||
if (i1 >= 92 && i1 <= 123)
|
||||
return 1;
|
||||
|
||||
/* 172.16.0.0/12 is reserved for private nets by RFC1819 */
|
||||
if (i1 == 172 && i2 >= 16 && i2 <= 31)
|
||||
return 1;
|
||||
|
||||
/* 173-187/8 is IANA reserved */
|
||||
if (i1 >= 173 && i1 <= 187)
|
||||
return 1;
|
||||
|
||||
/* 192.168.0.0/16 is reserved for private nets by RFC1819 */
|
||||
/* 192.0.2.0/24 is reserved for documentation and examples */
|
||||
/* 192.88.99.0/24 is used as 6to4 Relay anycast prefix by RFC3068 */
|
||||
if (i1 == 192) {
|
||||
if (i2 == 168)
|
||||
return 1;
|
||||
if (i2 == 0 && i3 == 2)
|
||||
return 1;
|
||||
if (i2 == 88 && i3 == 99)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 198.18.0.0/15 is used for benchmark tests by RFC2544 */
|
||||
if (i1 == 198 && i2 == 18 && i3 >= 1 && i3 <= 64) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* reserved for DHCP clients seeking addresses, not routable outside LAN */
|
||||
if (i1 == 169 && i2 == 254)
|
||||
return 1;
|
||||
|
||||
/* believe it or not, 204.152.64.0/23 is some bizarre Sun proprietary
|
||||
* clustering thing */
|
||||
if (i1 == 204 && i2 == 152 && (i3 == 64 || i3 == 65))
|
||||
return 1;
|
||||
|
||||
/* 224-239/8 is all multicast stuff */
|
||||
/* 240-255/8 is IANA reserved */
|
||||
if (i1 >= 224)
|
||||
return 1;
|
||||
|
||||
/* 255.255.255.255, note we already tested for i1 in this range */
|
||||
if (i2 == 255 && i3 == 255 && i4 == 255)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
char *grab_next_host_spec(FILE *inputfd, int argc, char **fakeargv) {
|
||||
static char host_spec[1024];
|
||||
unsigned int host_spec_index;
|
||||
int ch;
|
||||
struct in_addr ip;
|
||||
|
||||
if (o.generate_random_ips) {
|
||||
do {
|
||||
ip.s_addr = get_random_u32();
|
||||
} while (ip_is_reserved(&ip));
|
||||
Strncpy(host_spec, inet_ntoa(ip), sizeof(host_spec));
|
||||
} else if (!inputfd) {
|
||||
return( (optind < argc)? fakeargv[optind++] : NULL);
|
||||
} else {
|
||||
host_spec_index = 0;
|
||||
while((ch = getc(inputfd)) != EOF) {
|
||||
if (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t' || ch == '\0') {
|
||||
if (host_spec_index == 0) continue;
|
||||
host_spec[host_spec_index] = '\0';
|
||||
return host_spec;
|
||||
} else if (host_spec_index < sizeof(host_spec) / sizeof(char) -1) {
|
||||
host_spec[host_spec_index++] = (char) ch;
|
||||
} else fatal("One of the host_specifications from your input file is too long (> %d chars)", (int) sizeof(host_spec));
|
||||
}
|
||||
host_spec[host_spec_index] = '\0';
|
||||
}
|
||||
if (!*host_spec) return NULL;
|
||||
return host_spec;
|
||||
}
|
||||
|
||||
/* Just a routine for obtaining a string for printing based on the scantype */
|
||||
char *scantype2str(stype scantype) {
|
||||
@@ -2147,6 +2148,13 @@ void sigdie(int signo) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int fileexistsandisreadable(char *pathname) {
|
||||
FILE *fp;
|
||||
/* We check this the easy way! */
|
||||
fp = fopen(pathname, "r");
|
||||
if (fp) fclose(fp);
|
||||
return (fp == NULL)? 0 : 1;
|
||||
}
|
||||
|
||||
int nmap_fetchfile(char *filename_returned, int bufferlen, char *file) {
|
||||
char *dirptr;
|
||||
@@ -2260,11 +2268,4 @@ int nmap_fetchfile(char *filename_returned, int bufferlen, char *file) {
|
||||
|
||||
}
|
||||
|
||||
int fileexistsandisreadable(char *pathname) {
|
||||
FILE *fp;
|
||||
/* We check this the easy way! */
|
||||
fp = fopen(pathname, "r");
|
||||
if (fp) fclose(fp);
|
||||
return (fp == NULL)? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
4
nmap.h
4
nmap.h
@@ -426,8 +426,6 @@ void *realloc();
|
||||
|
||||
/***********************PROTOTYPES**********************************/
|
||||
|
||||
/* print usage information and exit */
|
||||
void printusage(char *name, int rc);
|
||||
/* print Interactive usage information */
|
||||
void printinteractiveusage();
|
||||
|
||||
@@ -454,7 +452,6 @@ int listen_icmp(int icmpsock, unsigned short outports[],
|
||||
int nmap_main(int argc, char *argv[]);
|
||||
|
||||
/* general helper functions */
|
||||
char *grab_next_host_spec(FILE *inputfd, int argc, char **fakeargv);
|
||||
int parse_targets(struct targets *targets, char *h);
|
||||
char *statenum2str(int state);
|
||||
char *scantype2str(stype scantype);
|
||||
@@ -469,7 +466,6 @@ char *tsseqclass2ascii(int seqclass);
|
||||
into a difficulty string like "Worthy Challenge */
|
||||
const char *seqidx2difficultystr(unsigned long idx);
|
||||
int nmap_fetchfile(char *filename_returned, int bufferlen, char *file);
|
||||
int fileexistsandisreadable(char *pathname);
|
||||
int gather_logfile_resumption_state(char *fname, int *myargc, char ***myargv);
|
||||
|
||||
/* From glibc 2.0.6 because Solaris doesn't seem to have this function */
|
||||
|
||||
482
nmap_dns.cc
482
nmap_dns.cc
@@ -199,7 +199,7 @@ extern NmapOps o;
|
||||
|
||||
// In milliseconds
|
||||
// Each row MUST be terminated with -1
|
||||
int read_timeouts[][4] = {
|
||||
static int read_timeouts[][4] = {
|
||||
{ 4000, 4000, 5000, -1 }, // 1 server
|
||||
{ 2500, 4000, -1, -1 }, // 2 servers
|
||||
{ 2500, 3000, -1, -1 }, // 3+ servers
|
||||
@@ -275,7 +275,6 @@ static std::list<request *> cname_reqs;
|
||||
static int total_reqs;
|
||||
static nsock_pool dnspool=NULL;
|
||||
|
||||
static int etchosts_filled=0;
|
||||
static std::list<host_elem *> etchosts[HASH_TABLE_SIZE];
|
||||
|
||||
static int stat_actual, stat_ok, stat_nx, stat_sf, stat_trans, stat_dropped, stat_cname;
|
||||
@@ -288,10 +287,7 @@ static ScanProgressMeter *SPM;
|
||||
|
||||
//------------------- Prototypes and macros ---------------------
|
||||
|
||||
void close_dns_servers();
|
||||
void write_evt_handler(nsock_pool nsp, nsock_event evt, void *req_v);
|
||||
void do_possible_writes();
|
||||
int deal_with_timedout_reads();
|
||||
void put_dns_packet_on_wire(request *req);
|
||||
|
||||
#define ACTION_FINISHED 0
|
||||
#define ACTION_CNAME_LIST 1
|
||||
@@ -301,7 +297,7 @@ int deal_with_timedout_reads();
|
||||
|
||||
//------------------- Misc code ---------------------
|
||||
|
||||
void output_summary() {
|
||||
static void output_summary() {
|
||||
int tp = stat_ok + stat_nx + stat_dropped;
|
||||
struct timeval now;
|
||||
|
||||
@@ -314,22 +310,206 @@ void output_summary() {
|
||||
(unsigned long) servs.size(), stat_ok, stat_nx, stat_dropped, stat_sf, stat_trans);
|
||||
}
|
||||
|
||||
|
||||
void check_capacities(dns_server *tpserv) {
|
||||
static void check_capacities(dns_server *tpserv) {
|
||||
if (tpserv->capacity < CAPACITY_MIN) tpserv->capacity = CAPACITY_MIN;
|
||||
if (tpserv->capacity > CAPACITY_MAX) tpserv->capacity = CAPACITY_MAX;
|
||||
if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "CAPACITY <%s> = %d\n", tpserv->hostname, tpserv->capacity);
|
||||
}
|
||||
|
||||
// Closes all nsis created in connect_dns_servers()
|
||||
static void close_dns_servers() {
|
||||
std::list<dns_server *>::iterator serverI;
|
||||
|
||||
for(serverI = servs.begin(); serverI != servs.end(); serverI++) {
|
||||
if ((*serverI)->connected) {
|
||||
nsi_delete((*serverI)->nsd, NSOCK_PENDING_SILENT);
|
||||
(*serverI)->connected = 0;
|
||||
(*serverI)->to_process.clear();
|
||||
(*serverI)->in_process.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Inserts an integer (endian non-specifically) into a DNS packet.
|
||||
// Returns number of bytes written
|
||||
static int add_integer_to_dns_packet(char *packet, int c) {
|
||||
char tpnum[4];
|
||||
int tplen;
|
||||
|
||||
//------------------- Read handling code ---------------------
|
||||
sprintf(tpnum, "%d", c);
|
||||
tplen = strlen(tpnum);
|
||||
packet[0] = (char) tplen;
|
||||
memcpy(packet+1, tpnum, tplen);
|
||||
|
||||
return tplen+1;
|
||||
}
|
||||
|
||||
// Puts as many packets on the line as capacity will allow
|
||||
static void do_possible_writes() {
|
||||
std::list<dns_server *>::iterator servI;
|
||||
dns_server *tpserv;
|
||||
request *tpreq;
|
||||
|
||||
for(servI = servs.begin(); servI != servs.end(); servI++) {
|
||||
tpserv = *servI;
|
||||
|
||||
if (tpserv->write_busy == 0 && tpserv->reqs_on_wire < tpserv->capacity) {
|
||||
tpreq = NULL;
|
||||
if (!tpserv->to_process.empty()) {
|
||||
tpreq = tpserv->to_process.front();
|
||||
tpserv->to_process.pop_front();
|
||||
} else if (!new_reqs.empty()) {
|
||||
tpreq = new_reqs.front();
|
||||
tpreq->first_server = tpreq->curr_server = tpserv;
|
||||
new_reqs.pop_front();
|
||||
}
|
||||
|
||||
if (tpreq) {
|
||||
if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: TRANSMITTING for <%s> (server <%s>)\n", tpreq->targ->targetipstr() , tpserv->hostname);
|
||||
stat_trans++;
|
||||
put_dns_packet_on_wire(tpreq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// nsock write handler
|
||||
static 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();
|
||||
}
|
||||
|
||||
// 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=0;
|
||||
u32 ip;
|
||||
struct timeval now, timeout;
|
||||
|
||||
ip = (u32) ntohl(req->targ->v4host().s_addr);
|
||||
|
||||
packet[0] = (req->id >> 8) & 0xFF;
|
||||
packet[1] = req->id & 0xFF;
|
||||
plen += 2;
|
||||
|
||||
memcpy(packet+plen, "\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00", 10);
|
||||
plen += 10;
|
||||
|
||||
plen += add_integer_to_dns_packet(packet+plen, ip & 0xFF);
|
||||
plen += add_integer_to_dns_packet(packet+plen, (ip>>8) & 0xFF);
|
||||
plen += add_integer_to_dns_packet(packet+plen, (ip>>16) & 0xFF);
|
||||
plen += add_integer_to_dns_packet(packet+plen, (ip>>24) & 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[read_timeout_index][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
|
||||
static int deal_with_timedout_reads() {
|
||||
std::list<dns_server *>::iterator servI;
|
||||
std::list<dns_server *>::iterator servItemp;
|
||||
std::list<request *>::iterator reqI;
|
||||
std::list<request *>::iterator nextI;
|
||||
dns_server *tpserv;
|
||||
request *tpreq;
|
||||
struct timeval now;
|
||||
int tp, min_timeout = INT_MAX;
|
||||
|
||||
memcpy(&now, nsock_gettimeofday(), sizeof(struct timeval));
|
||||
|
||||
if (keyWasPressed())
|
||||
SPM->printStats((double) (stat_ok + stat_nx + stat_dropped) / stat_actual, &now);
|
||||
|
||||
for(servI = servs.begin(); servI != servs.end(); servI++) {
|
||||
tpserv = *servI;
|
||||
|
||||
nextI = tpserv->in_process.begin();
|
||||
if (nextI == tpserv->in_process.end()) continue;
|
||||
|
||||
do {
|
||||
reqI = nextI++;
|
||||
tpreq = *reqI;
|
||||
|
||||
tp = TIMEVAL_MSEC_SUBTRACT(tpreq->timeout, now);
|
||||
if (tp > 0 && tp < min_timeout) min_timeout = tp;
|
||||
|
||||
if (tp <= 0) {
|
||||
tpserv->capacity = (int) (tpserv->capacity * CAPACITY_MINOR_DOWN_SCALE);
|
||||
check_capacities(tpserv);
|
||||
tpserv->in_process.erase(reqI);
|
||||
tpserv->reqs_on_wire--;
|
||||
|
||||
// If we've tried this server enough times, move to the next one
|
||||
if (read_timeouts[read_timeout_index][tpreq->tries] == -1) {
|
||||
tpserv->capacity = (int) (tpserv->capacity * CAPACITY_MAJOR_DOWN_SCALE);
|
||||
check_capacities(tpserv);
|
||||
|
||||
servItemp = servI;
|
||||
servItemp++;
|
||||
|
||||
if (servItemp == servs.end()) servItemp = servs.begin();
|
||||
|
||||
tpreq->curr_server = *servItemp;
|
||||
tpreq->tries = 0;
|
||||
tpreq->servers_tried++;
|
||||
|
||||
if (tpreq->curr_server == tpreq->first_server || tpreq->servers_tried == SERVERS_TO_TRY) {
|
||||
// Either give up on the IP
|
||||
// or, for maximum reliability, put the server back into processing
|
||||
// Note it's possible that this will never terminate.
|
||||
// FIXME: Find a good compromise
|
||||
|
||||
// **** We've already tried all servers... give up
|
||||
if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: *DR*OPPING <%s>\n", tpreq->targ->targetipstr());
|
||||
|
||||
output_summary();
|
||||
stat_dropped++;
|
||||
total_reqs--;
|
||||
delete tpreq;
|
||||
|
||||
// **** OR We start at the back of this server's queue
|
||||
//(*servItemp)->to_process.push_back(tpreq);
|
||||
} else {
|
||||
(*servItemp)->to_process.push_back(tpreq);
|
||||
}
|
||||
} else {
|
||||
tpserv->to_process.push_back(tpreq);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} while (nextI != tpserv->in_process.end());
|
||||
|
||||
}
|
||||
|
||||
if (min_timeout > 500) return 500;
|
||||
else return min_timeout;
|
||||
|
||||
}
|
||||
|
||||
// After processing a DNS response, we search through the IPs we're
|
||||
// looking for and update their results as necessary.
|
||||
// Returns non-zero if this matches a query we're looking for
|
||||
int process_result(u32 ia, char *result, int action, u16 id) {
|
||||
static int process_result(u32 ia, char *result, int action, u16 id) {
|
||||
std::list<dns_server *>::iterator servI;
|
||||
std::list<request *>::iterator reqI;
|
||||
dns_server *tpserv;
|
||||
@@ -381,7 +561,7 @@ int process_result(u32 ia, char *result, int action, u16 id) {
|
||||
// encoded string inside a packet.
|
||||
// maxlen is the very maximum length (in total bytes)
|
||||
// that should be processed
|
||||
u32 parse_inaddr_arpa(unsigned char *buf, int maxlen) {
|
||||
static u32 parse_inaddr_arpa(unsigned char *buf, int maxlen) {
|
||||
u32 ip=0;
|
||||
int i, j;
|
||||
|
||||
@@ -431,7 +611,7 @@ int encoded_name_to_normal(unsigned char *buf, char *output, int outputsize){
|
||||
|
||||
// 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(u8 *buf, int buflen, int curbuf,
|
||||
static int advance_past_dns_name(u8 *buf, int buflen, int curbuf,
|
||||
int *nameloc) {
|
||||
int compression=0;
|
||||
|
||||
@@ -458,10 +638,9 @@ int advance_past_dns_name(u8 *buf, int buflen, int curbuf,
|
||||
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) {
|
||||
static void read_evt_handler(nsock_pool nsp, nsock_event evt, void *nothing) {
|
||||
u8 *buf;
|
||||
int buflen, curbuf=0;
|
||||
int i, nameloc, rdlen, atype, aclass;
|
||||
@@ -592,205 +771,14 @@ void read_evt_handler(nsock_pool nsp, nsock_event evt, void *nothing) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------- 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, int c) {
|
||||
char tpnum[4];
|
||||
int tplen;
|
||||
|
||||
sprintf(tpnum, "%d", 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=0;
|
||||
u32 ip;
|
||||
struct timeval now, timeout;
|
||||
|
||||
ip = (u32) ntohl(req->targ->v4host().s_addr);
|
||||
|
||||
packet[0] = (req->id >> 8) & 0xFF;
|
||||
packet[1] = req->id & 0xFF;
|
||||
plen += 2;
|
||||
|
||||
memcpy(packet+plen, "\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00", 10);
|
||||
plen += 10;
|
||||
|
||||
plen += add_integer_to_dns_packet(packet+plen, ip & 0xFF);
|
||||
plen += add_integer_to_dns_packet(packet+plen, (ip>>8) & 0xFF);
|
||||
plen += add_integer_to_dns_packet(packet+plen, (ip>>16) & 0xFF);
|
||||
plen += add_integer_to_dns_packet(packet+plen, (ip>>24) & 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[read_timeout_index][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<dns_server *>::iterator servI;
|
||||
std::list<dns_server *>::iterator servItemp;
|
||||
std::list<request *>::iterator reqI;
|
||||
std::list<request *>::iterator nextI;
|
||||
dns_server *tpserv;
|
||||
request *tpreq;
|
||||
struct timeval now;
|
||||
int tp, min_timeout = INT_MAX;
|
||||
|
||||
memcpy(&now, nsock_gettimeofday(), sizeof(struct timeval));
|
||||
|
||||
if (keyWasPressed())
|
||||
SPM->printStats((double) (stat_ok + stat_nx + stat_dropped) / stat_actual, &now);
|
||||
|
||||
for(servI = servs.begin(); servI != servs.end(); servI++) {
|
||||
tpserv = *servI;
|
||||
|
||||
nextI = tpserv->in_process.begin();
|
||||
if (nextI == tpserv->in_process.end()) continue;
|
||||
|
||||
do {
|
||||
reqI = nextI++;
|
||||
tpreq = *reqI;
|
||||
|
||||
tp = TIMEVAL_MSEC_SUBTRACT(tpreq->timeout, now);
|
||||
if (tp > 0 && tp < min_timeout) min_timeout = tp;
|
||||
|
||||
if (tp <= 0) {
|
||||
tpserv->capacity = (int) (tpserv->capacity * CAPACITY_MINOR_DOWN_SCALE);
|
||||
check_capacities(tpserv);
|
||||
tpserv->in_process.erase(reqI);
|
||||
tpserv->reqs_on_wire--;
|
||||
|
||||
// If we've tried this server enough times, move to the next one
|
||||
if (read_timeouts[read_timeout_index][tpreq->tries] == -1) {
|
||||
tpserv->capacity = (int) (tpserv->capacity * CAPACITY_MAJOR_DOWN_SCALE);
|
||||
check_capacities(tpserv);
|
||||
|
||||
servItemp = servI;
|
||||
servItemp++;
|
||||
|
||||
if (servItemp == servs.end()) servItemp = servs.begin();
|
||||
|
||||
tpreq->curr_server = *servItemp;
|
||||
tpreq->tries = 0;
|
||||
tpreq->servers_tried++;
|
||||
|
||||
if (tpreq->curr_server == tpreq->first_server || tpreq->servers_tried == SERVERS_TO_TRY) {
|
||||
// Either give up on the IP
|
||||
// or, for maximum reliability, put the server back into processing
|
||||
// Note it's possible that this will never terminate.
|
||||
// FIXME: Find a good compromise
|
||||
|
||||
// **** We've already tried all servers... give up
|
||||
if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: *DR*OPPING <%s>\n", tpreq->targ->targetipstr());
|
||||
|
||||
output_summary();
|
||||
stat_dropped++;
|
||||
total_reqs--;
|
||||
delete tpreq;
|
||||
|
||||
// **** OR We start at the back of this server's queue
|
||||
//(*servItemp)->to_process.push_back(tpreq);
|
||||
} else {
|
||||
(*servItemp)->to_process.push_back(tpreq);
|
||||
}
|
||||
} else {
|
||||
tpserv->to_process.push_back(tpreq);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} while (nextI != tpserv->in_process.end());
|
||||
|
||||
}
|
||||
|
||||
if (min_timeout > 500) return 500;
|
||||
else return min_timeout;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Puts as many packets on the line as capacity will allow
|
||||
void do_possible_writes() {
|
||||
std::list<dns_server *>::iterator servI;
|
||||
dns_server *tpserv;
|
||||
request *tpreq;
|
||||
|
||||
for(servI = servs.begin(); servI != servs.end(); servI++) {
|
||||
tpserv = *servI;
|
||||
|
||||
if (tpserv->write_busy == 0 && tpserv->reqs_on_wire < tpserv->capacity) {
|
||||
tpreq = NULL;
|
||||
if (!tpserv->to_process.empty()) {
|
||||
tpreq = tpserv->to_process.front();
|
||||
tpserv->to_process.pop_front();
|
||||
} else if (!new_reqs.empty()) {
|
||||
tpreq = new_reqs.front();
|
||||
tpreq->first_server = tpreq->curr_server = tpserv;
|
||||
new_reqs.pop_front();
|
||||
}
|
||||
|
||||
if (tpreq) {
|
||||
if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: TRANSMITTING for <%s> (server <%s>)\n", tpreq->targ->targetipstr() , tpserv->hostname);
|
||||
stat_trans++;
|
||||
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) {
|
||||
static void connect_evt_handler(nsock_pool nsp, nsock_event evt, void *servers) {
|
||||
}
|
||||
|
||||
|
||||
// Adds DNS servers to the dns_server list. They can be separated by
|
||||
// commas or spaces - NOTE this doesn't actually do any connecting!
|
||||
void add_dns_server(char *ipaddrs) {
|
||||
static void add_dns_server(char *ipaddrs) {
|
||||
std::list<dns_server *>::iterator servI;
|
||||
dns_server *tpserv;
|
||||
char *hostname;
|
||||
@@ -846,21 +834,6 @@ void connect_dns_servers() {
|
||||
}
|
||||
|
||||
|
||||
// Closes all nsis created in connect_dns_servers()
|
||||
void close_dns_servers() {
|
||||
std::list<dns_server *>::iterator serverI;
|
||||
|
||||
for(serverI = servs.begin(); serverI != servs.end(); serverI++) {
|
||||
if ((*serverI)->connected) {
|
||||
nsi_delete((*serverI)->nsd, NSOCK_PENDING_SILENT);
|
||||
(*serverI)->connected = 0;
|
||||
(*serverI)->to_process.clear();
|
||||
(*serverI)->in_process.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
void win32_read_registry(char *controlset) {
|
||||
HKEY hKey;
|
||||
@@ -921,7 +894,7 @@ void win32_read_registry(char *controlset) {
|
||||
|
||||
// Parses /etc/resolv.conf (unix) or the registry (win32) and adds
|
||||
// all the nameservers found via the add_dns_server() function.
|
||||
void parse_resolvdotconf() {
|
||||
static void parse_resolvdotconf() {
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
@@ -956,7 +929,7 @@ void parse_resolvdotconf() {
|
||||
}
|
||||
|
||||
|
||||
void parse_etchosts(char *fname) {
|
||||
static void parse_etchosts(char *fname) {
|
||||
FILE *fp;
|
||||
char buf[2048], hname[256], ipaddrstr[16], *tp;
|
||||
struct in_addr ia;
|
||||
@@ -990,7 +963,7 @@ void parse_etchosts(char *fname) {
|
||||
}
|
||||
|
||||
|
||||
char *lookup_etchosts(u32 ip) {
|
||||
static char *lookup_etchosts(u32 ip) {
|
||||
std::list<host_elem *>::iterator hostI;
|
||||
host_elem *tpelem;
|
||||
|
||||
@@ -1003,13 +976,41 @@ char *lookup_etchosts(u32 ip) {
|
||||
}
|
||||
|
||||
|
||||
static void etchosts_init(void) {
|
||||
static int initialized = 0;
|
||||
if (initialized) return;
|
||||
initialized = 1;
|
||||
|
||||
#ifdef WIN32
|
||||
char windows_dir[1024];
|
||||
char tpbuf[2048];
|
||||
int has_backslash;
|
||||
|
||||
if (!GetWindowsDirectory(windows_dir, sizeof(windows_dir)))
|
||||
fatal("Failed to determine your windows directory");
|
||||
|
||||
// If it has a backslash it's C:\, otherwise something like C:\WINNT
|
||||
has_backslash = (windows_dir[strlen(windows_dir)-1] == '\\');
|
||||
|
||||
// Windows 95/98/Me:
|
||||
snprintf(tpbuf, sizeof(tpbuf), "%s%shosts", windows_dir, has_backslash ? "" : "\\");
|
||||
parse_etchosts(tpbuf);
|
||||
|
||||
// Windows NT/2000/XP/2K3:
|
||||
snprintf(tpbuf, sizeof(tpbuf), "%s%ssystem32\\drivers\\etc\\hosts", windows_dir, has_backslash ? "" : "\\");
|
||||
parse_etchosts(tpbuf);
|
||||
|
||||
#else
|
||||
parse_etchosts("/etc/hosts");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//------------------- Main loops ---------------------
|
||||
|
||||
|
||||
// Actual main loop
|
||||
void nmap_mass_rdns_core(Target **targets, int num_targets) {
|
||||
static void nmap_mass_rdns_core(Target **targets, int num_targets) {
|
||||
|
||||
Target **hostI;
|
||||
std::list<request *>::iterator reqI;
|
||||
@@ -1066,32 +1067,7 @@ void nmap_mass_rdns_core(Target **targets, int num_targets) {
|
||||
|
||||
|
||||
// If necessary, set up the /etc/hosts hashtable
|
||||
if (etchosts_filled == 0) {
|
||||
#ifdef WIN32
|
||||
char windows_dir[1024];
|
||||
char tpbuf[2048];
|
||||
int has_backslash;
|
||||
|
||||
if (!GetWindowsDirectory(windows_dir, sizeof(windows_dir)))
|
||||
fatal("Failed to determine your windows directory");
|
||||
|
||||
// If it has a backslash it's C:\, otherwise something like C:\WINNT
|
||||
has_backslash = (windows_dir[strlen(windows_dir)-1] == '\\');
|
||||
|
||||
// Windows 95/98/Me:
|
||||
snprintf(tpbuf, sizeof(tpbuf), "%s%shosts", windows_dir, has_backslash ? "" : "\\");
|
||||
parse_etchosts(tpbuf);
|
||||
|
||||
// Windows NT/2000/XP/2K3:
|
||||
snprintf(tpbuf, sizeof(tpbuf), "%s%ssystem32\\drivers\\etc\\hosts", windows_dir, has_backslash ? "" : "\\");
|
||||
parse_etchosts(tpbuf);
|
||||
|
||||
#else
|
||||
parse_etchosts("/etc/hosts");
|
||||
#endif
|
||||
|
||||
etchosts_filled = 1;
|
||||
}
|
||||
etchosts_init();
|
||||
|
||||
|
||||
total_reqs = 0;
|
||||
|
||||
12
nmap_rpc.cc
12
nmap_rpc.cc
@@ -106,7 +106,6 @@
|
||||
#include "NmapOps.h"
|
||||
|
||||
extern NmapOps o;
|
||||
static int services_initialized = 0;
|
||||
static struct rpc_info ri;
|
||||
static int udp_rpc_socket = -1;
|
||||
static int tcp_rpc_socket = -1;
|
||||
@@ -119,13 +118,16 @@ static size_t tcp_readlen=0; /* used in get_rpc_results but can be reset in
|
||||
send_rpc_query */
|
||||
|
||||
static void rpc_services_init() {
|
||||
static int services_initialized = 0;
|
||||
if (services_initialized) return;
|
||||
services_initialized = 1;
|
||||
|
||||
char filename[512];
|
||||
FILE *fp;
|
||||
char *tmpptr, *p;
|
||||
char line[1024];
|
||||
int lineno = 0;
|
||||
|
||||
services_initialized = 1;
|
||||
ri.num_alloc = 256;
|
||||
ri.num_used = 0;
|
||||
ri.names = (char **) cp_alloc(ri.num_alloc * sizeof(char *));
|
||||
@@ -182,9 +184,7 @@ static void rpc_services_init() {
|
||||
char *nmap_getrpcnamebynum(unsigned long num) {
|
||||
int i;
|
||||
|
||||
if (!services_initialized) {
|
||||
rpc_services_init();
|
||||
}
|
||||
|
||||
for(i=0; i < ri.num_used; i++) {
|
||||
if (ri.numbers[i] == num)
|
||||
@@ -194,9 +194,7 @@ char *nmap_getrpcnamebynum(unsigned long num) {
|
||||
}
|
||||
|
||||
int get_rpc_procs(unsigned long **programs, unsigned long *num_programs) {
|
||||
if (!services_initialized) {
|
||||
rpc_services_init();
|
||||
}
|
||||
|
||||
*programs = ri.numbers;
|
||||
*num_programs = ri.num_used;
|
||||
@@ -332,7 +330,7 @@ int send_rpc_query(const struct in_addr *target_host, unsigned short portno,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpc_are_we_done(char *msg, int msg_len, Target *target,
|
||||
static int rpc_are_we_done(char *msg, int msg_len, Target *target,
|
||||
struct portinfo *scan, struct scanstats *ss,
|
||||
struct portinfolist *pil, struct rpcscaninfo *rsi) {
|
||||
|
||||
|
||||
22
osscan.h
22
osscan.h
@@ -120,11 +120,6 @@
|
||||
|
||||
/********************** PROTOTYPES ***********************************/
|
||||
int os_scan(Target *target);
|
||||
FingerPrint *get_fingerprint(Target *target, struct seq_info *si);
|
||||
struct AVal *fingerprint_iptcppacket(struct ip *ip, int mss, unsigned int syn);
|
||||
struct AVal *fingerprint_portunreach(struct ip *ip, struct udpprobeinfo *upi);
|
||||
unsigned int get_gcd_n_ulong(int numvalues, unsigned int *values);
|
||||
unsigned int euclid_gcd(unsigned int a, unsigned int b);
|
||||
char *fp2ascii(FingerPrint *FP);
|
||||
|
||||
/* Parses a single fingerprint from the memory region given. If a
|
||||
@@ -151,30 +146,13 @@ double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP,
|
||||
FingerPrintResults class. */
|
||||
void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
|
||||
FingerPrint **reference_FPs, double accuracy_threshold);
|
||||
struct AVal *str2AVal(char *p);
|
||||
struct AVal *gettestbyname(FingerPrint *FP, const char *name);
|
||||
|
||||
/* Returns true if perfect match -- if num_subtests & num_subtests_succeeded are non_null it updates them. if shortcircuit is zero, it does all the tests, otherwise it returns when the first one fails */
|
||||
|
||||
/* Returns true if perfect match -- if num_subtests &
|
||||
num_subtests_succeeded are non_null it ADDS THE NEW VALUES to what
|
||||
is already there. So initialize them to zero first if you only
|
||||
want to see the results from this match. if shortcircuit is zero,
|
||||
it does all the tests, otherwise it returns when the first one
|
||||
fails */
|
||||
int AVal_match(struct AVal *reference, struct AVal *fprint, unsigned long *num_subtests, unsigned long *num_subtests_succeeded, int shortcut);
|
||||
|
||||
void freeFingerPrint(FingerPrint *FP);
|
||||
char *mergeFPs(FingerPrint *FPs[], int numFPs, int openport, int closedport,
|
||||
const u8 *mac);
|
||||
|
||||
/* Writes an informational "Test" result suitable for including at the
|
||||
top of a fingerprint. Gives info which might be useful when the
|
||||
FPrint is submitted (eg Nmap version, etc). Result is written (up
|
||||
to ostrlen) to the ostr var passed in */
|
||||
void WriteSInfo(char *ostr, int ostrlen, int openport, int closedport,
|
||||
const u8 *mac);
|
||||
|
||||
/* This function takes an array of "numSamples" IP IDs and analyzes
|
||||
them to determine their sequenceability classification. It returns
|
||||
one of the IPID_SEQ_* classifications defined in nmap.h . If the
|
||||
|
||||
43
output.cc
43
output.cc
@@ -119,7 +119,7 @@ extern NmapOps o;
|
||||
static char *logtypes[LOG_NUM_FILES]=LOG_NAMES;
|
||||
|
||||
/* Used in creating skript kiddie style output. |<-R4d! */
|
||||
void skid_output(char *s)
|
||||
static void skid_output(char *s)
|
||||
{
|
||||
int i;
|
||||
for (i=0;s[i];i++)
|
||||
@@ -824,7 +824,7 @@ int log_open(int logt, int append, char *filename)
|
||||
/* The items in ports should be
|
||||
in sequential order for space savings and easier to read output. Outputs
|
||||
the rangelist to the log stream given (such as LOG_MACHINE or LOG_XML) */
|
||||
void output_rangelist_given_ports(int logt, unsigned short *ports,
|
||||
static void output_rangelist_given_ports(int logt, unsigned short *ports,
|
||||
int numports) {
|
||||
int i, previous_port = -2, range_start = -2, port;
|
||||
char outpbuf[128];
|
||||
@@ -907,6 +907,26 @@ void output_xml_scaninfo_records(struct scan_lists *scanlist) {
|
||||
log_flush_all();
|
||||
}
|
||||
|
||||
/* Prints the MAC address (if discovered) to XML output */
|
||||
static void print_MAC_XML_Info(Target *currenths) {
|
||||
const u8 *mac = currenths->MACAddress();
|
||||
char macascii[32];
|
||||
char vendorstr[128];
|
||||
char *xml_mac = NULL;
|
||||
|
||||
if (mac) {
|
||||
const char *macvendor = MACPrefix2Corp(mac);
|
||||
snprintf(macascii, sizeof(macascii), "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
if (macvendor) {
|
||||
xml_mac = xml_convert(macvendor);
|
||||
snprintf(vendorstr, sizeof(vendorstr), " vendor=\"%s\"", xml_mac);
|
||||
free(xml_mac);
|
||||
} else vendorstr[0] = '\0';
|
||||
log_write(LOG_XML, "<address addr=\"%s\" addrtype=\"mac\"%s />\n", macascii, vendorstr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper function to write the status and address/hostname info of a host
|
||||
into the XML log */
|
||||
static void write_xml_initial_hostinfo(Target *currenths,
|
||||
@@ -1139,25 +1159,6 @@ void printmacinfo(Target *currenths) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Prints the MAC address (if discovered) to XML output */
|
||||
void print_MAC_XML_Info(Target *currenths) {
|
||||
const u8 *mac = currenths->MACAddress();
|
||||
char macascii[32];
|
||||
char vendorstr[128];
|
||||
char *xml_mac = NULL;
|
||||
|
||||
if (mac) {
|
||||
const char *macvendor = MACPrefix2Corp(mac);
|
||||
snprintf(macascii, sizeof(macascii), "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
if (macvendor) {
|
||||
xml_mac = xml_convert(macvendor);
|
||||
snprintf(vendorstr, sizeof(vendorstr), " vendor=\"%s\"", xml_mac);
|
||||
free(xml_mac);
|
||||
} else vendorstr[0] = '\0';
|
||||
log_write(LOG_XML, "<address addr=\"%s\" addrtype=\"mac\"%s />\n", macascii, vendorstr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Prints the formatted OS Scan output to stdout, logfiles, etc (but only
|
||||
|
||||
13
output.h
13
output.h
@@ -136,9 +136,6 @@ void printportoutput(Target *currenths, PortList *plist);
|
||||
in a certain place to conform to DTD. */
|
||||
void printmacinfo(Target *currenths);
|
||||
|
||||
/* Prints the MAC address (if discovered) to XML output */
|
||||
void print_MAC_XML_Info(Target *currenths);
|
||||
|
||||
/* Write some information (printf style args) to the given log stream(s).
|
||||
Remember to watch out for format string bugs. */
|
||||
void log_write(int logt, const char *fmt, ...)
|
||||
@@ -168,9 +165,6 @@ void log_flush_all();
|
||||
it already exists. If the file does not exist, it will be created */
|
||||
int log_open(int logt, int append, char *filename);
|
||||
|
||||
/* Used in creating skript kiddie style output. |<-R4d! */
|
||||
void skid_output(char *s);
|
||||
|
||||
/* Output the list of ports scanned to the top of machine parseable
|
||||
logs (in a comment, unfortunately). The items in ports should be
|
||||
in sequential order for space savings and easier to read output */
|
||||
@@ -178,13 +172,6 @@ void output_ports_to_machine_parseable_output(struct scan_lists *ports,
|
||||
int tcpscan, int udpscan,
|
||||
int protscan);
|
||||
|
||||
/* The items in ports should be
|
||||
in sequential order for space savings and easier to read output. Outputs
|
||||
the rangelist to the log stream given (such as LOG_MACHINE or LOG_XML) */
|
||||
void output_rangelist_given_ports(int logt, unsigned short *ports,
|
||||
int numports);
|
||||
|
||||
|
||||
/* Similar to output_ports_to_machine_parseable_output, this function
|
||||
outputs the XML version, which is scaninfo records of each scan
|
||||
requested and the ports which it will scan for */
|
||||
|
||||
@@ -103,11 +103,13 @@
|
||||
#include "NmapOps.h"
|
||||
|
||||
extern NmapOps o;
|
||||
static int protocols_initialized = 0;
|
||||
static int numipprots = 0;
|
||||
static struct protocol_list *protocol_table[PROTOCOL_TABLE_SIZE];
|
||||
|
||||
static int nmap_protocols_init() {
|
||||
static int protocols_initialized = 0;
|
||||
if (protocols_initialized) return 0;
|
||||
|
||||
char filename[512];
|
||||
FILE *fp;
|
||||
char protocolname[128];
|
||||
@@ -179,7 +181,6 @@ static int nmap_protocols_init() {
|
||||
struct protoent *nmap_getprotbynum(int num) {
|
||||
struct protocol_list *current;
|
||||
|
||||
if (!protocols_initialized)
|
||||
if (nmap_protocols_init() == -1)
|
||||
return NULL;
|
||||
|
||||
@@ -202,7 +203,6 @@ struct scan_lists *getdefaultprots(void) {
|
||||
int bucket;
|
||||
int protsneeded = 256;
|
||||
|
||||
if (!protocols_initialized)
|
||||
if (nmap_protocols_init() == -1)
|
||||
fatal("getdefaultprots(): Couldn't get protocol numbers");
|
||||
|
||||
@@ -224,7 +224,6 @@ struct scan_lists *getfastprots(void) {
|
||||
int bucket;
|
||||
int protsneeded = 0;
|
||||
|
||||
if (!protocols_initialized)
|
||||
if (nmap_protocols_init() == -1)
|
||||
fatal("Getfastprots: Couldn't get protocol numbers");
|
||||
|
||||
|
||||
444
scan_engine.cc
444
scan_engine.cc
@@ -576,9 +576,6 @@ private:
|
||||
|
||||
};
|
||||
|
||||
bool ultrascan_port_pspec_update(UltraScanInfo *USI, HostScanStats *hss,
|
||||
const probespec *pspec, int newstate);
|
||||
|
||||
/* Whether this is storing timing stats for a whole group or an
|
||||
individual host */
|
||||
enum ultra_timing_type { TIMING_HOST, TIMING_GROUP };
|
||||
@@ -590,11 +587,6 @@ static void init_ultra_timing_vals(ultra_timing_vals *timing,
|
||||
int num_hosts_in_group,
|
||||
struct ultra_scan_performance_vars *perf,
|
||||
struct timeval *now);
|
||||
/* Adjust various timing variables based on pcket receipt. Pass
|
||||
rcvdtime = NULL if you have given up on a probe and want to count
|
||||
this as a DROPPED PACKET */
|
||||
void ultrascan_adjust_times(UltraScanInfo *USI, HostScanStats *hss,
|
||||
UltraProbe *probe, struct timeval *rcvdtime);
|
||||
|
||||
/* Take a buffer, buf, of size bufsz (32 bytes is sufficient) and
|
||||
writes a short description of the probe (arg1) into buf. It also returns
|
||||
@@ -1495,189 +1487,10 @@ void HostScanStats::destroyOutstandingProbe(list<UltraProbe *>::iterator probeI)
|
||||
delete probe;
|
||||
}
|
||||
|
||||
/* Mark an outstanding probe as timedout. Adjusts stats
|
||||
accordingly. For connect scans, this closes the socket. */
|
||||
void HostScanStats::markProbeTimedout(list<UltraProbe *>::iterator probeI) {
|
||||
UltraProbe *probe = *probeI;
|
||||
assert(!probe->timedout);
|
||||
assert(!probe->retransmitted);
|
||||
probe->timedout = true;
|
||||
assert(num_probes_active > 0);
|
||||
num_probes_active--;
|
||||
assert(USI->gstats->num_probes_active > 0);
|
||||
USI->gstats->num_probes_active--;
|
||||
if (probe->isPing()) {
|
||||
ultrascan_adjust_times(USI, this, probe, NULL);
|
||||
/* I'll leave it in the queue in case some response ever does
|
||||
come */
|
||||
} else num_probes_waiting_retransmit++;
|
||||
|
||||
if (probe->type == UltraProbe::UP_CONNECT && probe->CP()->sd >= 0 ) {
|
||||
/* Free the socket as that is a valuable resource, though it is a shame
|
||||
late responses will not be permitted */
|
||||
USI->gstats->CSI->clearSD(probe->CP()->sd);
|
||||
close(probe->CP()->sd);
|
||||
probe->CP()->sd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool HostScanStats::completed() {
|
||||
return num_probes_active == 0 && num_probes_waiting_retransmit == 0 &&
|
||||
probe_bench.empty() && retry_stack.empty() && freshPortsLeft() == 0;
|
||||
}
|
||||
|
||||
/* Encode the trynum into a 32-bit value. A simple checksum is also included
|
||||
to verify whether a received version is correct. */
|
||||
static u32 seq32_encode(UltraScanInfo *USI, unsigned int trynum,
|
||||
unsigned int pingseq) {
|
||||
u32 seq = 0;
|
||||
u16 nfo;
|
||||
|
||||
/* We'll let pingseq and trynum each be 8 bits */
|
||||
nfo = (pingseq << 8) + trynum;
|
||||
seq = (nfo << 16) + nfo; /* Mirror the data to ensure it is reconstructed correctly */
|
||||
/* Obfuscate it a little */
|
||||
seq = seq ^ USI->seqmask;
|
||||
return seq;
|
||||
}
|
||||
|
||||
/* This function provides the proper cwnd and ccthresh to use. It may
|
||||
differ from versions in timing member var because when no responses
|
||||
have been received for this host, may look at others in the group.
|
||||
For CHANGING this host's timing, use the timing memberval
|
||||
instead. */
|
||||
void HostScanStats::getTiming(struct ultra_timing_vals *tmng) {
|
||||
assert(tmng);
|
||||
|
||||
/* Use the per-host value if a pingport has been found or very few probes
|
||||
have been sent */
|
||||
if (pingprobestate != PORT_UNKNOWN || numprobes_sent < 80) {
|
||||
*tmng = timing;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise, use the global cwnd stats if it has sufficient responses */
|
||||
if (USI->gstats->timing.num_updates > 1) {
|
||||
*tmng = USI->gstats->timing;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Last resort is to use canned values */
|
||||
tmng->cwnd = USI->perf.host_initial_cwnd;
|
||||
tmng->ccthresh = USI->perf.initial_ccthresh;
|
||||
tmng->num_updates = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Boost the scan delay for this host, usually because too many packet
|
||||
drops were detected. */
|
||||
void HostScanStats::boostScanDelay() {
|
||||
unsigned int maxAllowed = (USI->tcp_scan)? o.maxTCPScanDelay() : o.maxUDPScanDelay();
|
||||
if (sdn.delayms == 0)
|
||||
sdn.delayms = (USI->udp_scan)? 50 : 5; // In many cases, a pcap wait takes a minimum of 80ms, so this matters little :(
|
||||
else sdn.delayms = MIN(sdn.delayms * 2, MAX(sdn.delayms, 1000));
|
||||
sdn.delayms = MIN(sdn.delayms, maxAllowed);
|
||||
sdn.last_boost = USI->now;
|
||||
sdn.droppedRespSinceDelayChanged = 0;
|
||||
sdn.goodRespSinceDelayChanged = 0;
|
||||
}
|
||||
|
||||
/* Dismiss all probe attempts on bench -- the ports are marked
|
||||
'filtered' or whatever is appropriate for having no response */
|
||||
void HostScanStats::dismissBench() {
|
||||
int newstate;
|
||||
|
||||
if (probe_bench.empty()) return;
|
||||
newstate = scantype_no_response_means(USI->scantype);
|
||||
while(!probe_bench.empty()) {
|
||||
ultrascan_port_pspec_update(USI, this, &probe_bench.back(), newstate);
|
||||
probe_bench.pop_back();
|
||||
}
|
||||
bench_tryno = 0;
|
||||
}
|
||||
|
||||
/* Move all members of bench to retry_stack for probe retransmission */
|
||||
void HostScanStats::retransmitBench() {
|
||||
int newstate;
|
||||
if (probe_bench.empty()) return;
|
||||
|
||||
/* Move all contents of probe_bench to the end of retry_stack, updating retry_stack_tries accordingly */
|
||||
retry_stack.insert(retry_stack.end(), probe_bench.begin(), probe_bench.end());
|
||||
retry_stack_tries.insert(retry_stack_tries.end(), probe_bench.size(),
|
||||
bench_tryno);
|
||||
assert(retry_stack.size() == retry_stack_tries.size());
|
||||
probe_bench.erase(probe_bench.begin(), probe_bench.end());
|
||||
newstate = scantype_no_response_means(USI->scantype);
|
||||
bench_tryno = 0;
|
||||
}
|
||||
|
||||
/* Moves the given probe from the probes_outstanding list, to
|
||||
probe_bench, and decrements num_probes_waiting_retransmit
|
||||
accordingly */
|
||||
void HostScanStats::moveProbeToBench(list<UltraProbe *>::iterator probeI) {
|
||||
UltraProbe *probe = *probeI;
|
||||
if (!probe_bench.empty())
|
||||
assert(bench_tryno == probe->tryno);
|
||||
else {
|
||||
bench_tryno = probe->tryno;
|
||||
probe_bench.reserve(128);
|
||||
}
|
||||
probe_bench.push_back(*probe->pspec());
|
||||
probes_outstanding.erase(probeI);
|
||||
num_probes_waiting_retransmit--;
|
||||
delete probe;
|
||||
}
|
||||
|
||||
/* Undoes seq32_encode. Returns true if the checksum is correct and
|
||||
thus trynum was decoded properly. In that case, trynum (if not
|
||||
null) is filled with the decoded value. If pingseq is not null, it
|
||||
is filled with the scanping sequence number, which is 0 if this is
|
||||
not a ping. */
|
||||
|
||||
static bool seq32_decode(UltraScanInfo *USI, u32 seq, unsigned int *trynum,
|
||||
unsigned int *pingseq) {
|
||||
if (trynum) *trynum = 0;
|
||||
if (pingseq) *pingseq = 0;
|
||||
|
||||
/* Undo the mask xor */
|
||||
seq = seq ^ USI->seqmask;
|
||||
/* Check that both sides are the same */
|
||||
if ((seq >> 16) != (seq & 0xFFFF))
|
||||
return false;
|
||||
|
||||
if (trynum)
|
||||
*trynum = seq & 0xFF;
|
||||
|
||||
if (pingseq)
|
||||
*pingseq = (seq & 0xFF00) >> 8;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Sometimes the trynumber and/or pingseq are stored in a source
|
||||
portnumber of probes instead. This takes a port number in HOST
|
||||
BYTE ORDER. Returns true if the numbers seem reasonable, false if
|
||||
they are bogus. */
|
||||
bool sport_decode(UltraScanInfo *USI, u16 portno, unsigned int *trynum,
|
||||
unsigned int *pingseq) {
|
||||
int tryval;
|
||||
tryval = portno - o.magic_port;
|
||||
if (tryval <= USI->perf.tryno_cap) {
|
||||
if (pingseq) *pingseq = 0;
|
||||
if (trynum) *trynum = tryval;
|
||||
} else {
|
||||
if (pingseq) *pingseq = tryval - USI->perf.tryno_cap;
|
||||
if (trynum) *trynum = 0;
|
||||
}
|
||||
if (tryval > USI->perf.tryno_cap + 256)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Adjust various timing variables based on pcket receipt. Pass
|
||||
rcvdtime = NULL if you have given up on a probe and want to count
|
||||
this as a DROPPED PACKET */
|
||||
void ultrascan_adjust_times(UltraScanInfo *USI, HostScanStats *hss,
|
||||
static void ultrascan_adjust_times(UltraScanInfo *USI, HostScanStats *hss,
|
||||
UltraProbe *probe, struct timeval *rcvdtime) {
|
||||
|
||||
int ping_magnifier = (probe->isPing())? USI->perf.ping_magnifier : 1;
|
||||
@@ -1762,48 +1575,87 @@ void ultrascan_adjust_times(UltraScanInfo *USI, HostScanStats *hss,
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when a ping response is discovered. */
|
||||
static void ultrascan_ping_update(UltraScanInfo *USI, HostScanStats *hss,
|
||||
list<UltraProbe *>::iterator probeI,
|
||||
struct timeval *rcvdtime) {
|
||||
ultrascan_adjust_times(USI, hss, *probeI, rcvdtime);
|
||||
hss->destroyOutstandingProbe(probeI);
|
||||
/* Mark an outstanding probe as timedout. Adjusts stats
|
||||
accordingly. For connect scans, this closes the socket. */
|
||||
void HostScanStats::markProbeTimedout(list<UltraProbe *>::iterator probeI) {
|
||||
UltraProbe *probe = *probeI;
|
||||
assert(!probe->timedout);
|
||||
assert(!probe->retransmitted);
|
||||
probe->timedout = true;
|
||||
assert(num_probes_active > 0);
|
||||
num_probes_active--;
|
||||
assert(USI->gstats->num_probes_active > 0);
|
||||
USI->gstats->num_probes_active--;
|
||||
if (probe->isPing()) {
|
||||
ultrascan_adjust_times(USI, this, probe, NULL);
|
||||
/* I'll leave it in the queue in case some response ever does
|
||||
come */
|
||||
} else num_probes_waiting_retransmit++;
|
||||
|
||||
if (probe->type == UltraProbe::UP_CONNECT && probe->CP()->sd >= 0 ) {
|
||||
/* Free the socket as that is a valuable resource, though it is a shame
|
||||
late responses will not be permitted */
|
||||
USI->gstats->CSI->clearSD(probe->CP()->sd);
|
||||
close(probe->CP()->sd);
|
||||
probe->CP()->sd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool HostScanStats::completed() {
|
||||
return num_probes_active == 0 && num_probes_waiting_retransmit == 0 &&
|
||||
probe_bench.empty() && retry_stack.empty() && freshPortsLeft() == 0;
|
||||
}
|
||||
|
||||
/* Called when a new status is determined for host in hss (eg. it is
|
||||
found to be up or down by a ping/ping_arp scan. The probe that led
|
||||
to this new decision is in probeI. This function needs to update
|
||||
timing information and other stats as appropriate.If rcvdtime is
|
||||
NULL, packet stats are not updated. */
|
||||
static void ultrascan_host_update(UltraScanInfo *USI, HostScanStats *hss,
|
||||
list<UltraProbe *>::iterator probeI,
|
||||
int newstate, struct timeval *rcvdtime) {
|
||||
UltraProbe *probe = *probeI;
|
||||
if (rcvdtime) ultrascan_adjust_times(USI, hss, probe, rcvdtime);
|
||||
/* Encode the trynum into a 32-bit value. A simple checksum is also included
|
||||
to verify whether a received version is correct. */
|
||||
static u32 seq32_encode(UltraScanInfo *USI, unsigned int trynum,
|
||||
unsigned int pingseq) {
|
||||
u32 seq = 0;
|
||||
u16 nfo;
|
||||
|
||||
/* Adjust the target flags to note the new state. */
|
||||
if ((hss->target->flags & HOST_UP) == 0) {
|
||||
if (newstate == HOST_UP) {
|
||||
/* Clear any HOST_DOWN or HOST_FIREWALLED flags */
|
||||
hss->target->flags &= ~(HOST_DOWN|HOST_FIREWALLED);
|
||||
hss->target->flags |= HOST_UP;
|
||||
} else if (newstate == HOST_DOWN) {
|
||||
hss->target->flags &= ~HOST_FIREWALLED;
|
||||
hss->target->flags |= HOST_DOWN;
|
||||
} else assert(0);
|
||||
/* We'll let pingseq and trynum each be 8 bits */
|
||||
nfo = (pingseq << 8) + trynum;
|
||||
seq = (nfo << 16) + nfo; /* Mirror the data to ensure it is reconstructed correctly */
|
||||
/* Obfuscate it a little */
|
||||
seq = seq ^ USI->seqmask;
|
||||
return seq;
|
||||
}
|
||||
|
||||
/* This function provides the proper cwnd and ccthresh to use. It may
|
||||
differ from versions in timing member var because when no responses
|
||||
have been received for this host, may look at others in the group.
|
||||
For CHANGING this host's timing, use the timing memberval
|
||||
instead. */
|
||||
void HostScanStats::getTiming(struct ultra_timing_vals *tmng) {
|
||||
assert(tmng);
|
||||
|
||||
/* Use the per-host value if a pingport has been found or very few probes
|
||||
have been sent */
|
||||
if (pingprobestate != PORT_UNKNOWN || numprobes_sent < 80) {
|
||||
*tmng = timing;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Kill outstanding probes */
|
||||
while(!hss->probes_outstanding.empty())
|
||||
hss->destroyOutstandingProbe(hss->probes_outstanding.begin());
|
||||
/* Otherwise, use the global cwnd stats if it has sufficient responses */
|
||||
if (USI->gstats->timing.num_updates > 1) {
|
||||
*tmng = USI->gstats->timing;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Last resort is to use canned values */
|
||||
tmng->cwnd = USI->perf.host_initial_cwnd;
|
||||
tmng->ccthresh = USI->perf.initial_ccthresh;
|
||||
tmng->num_updates = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Like ultrascan_port_probe_update(), except it is called with just a
|
||||
probespec rather than a whole UltraProbe. Returns true if the port
|
||||
was added or at least the state was changed. */
|
||||
bool ultrascan_port_pspec_update(UltraScanInfo *USI, HostScanStats *hss,
|
||||
const probespec *pspec, int newstate) {
|
||||
static bool ultrascan_port_pspec_update(UltraScanInfo *USI,
|
||||
HostScanStats *hss,
|
||||
const probespec *pspec,
|
||||
int newstate) {
|
||||
u16 portno;
|
||||
u8 proto = 0;
|
||||
int oldstate = PORT_TESTING;
|
||||
@@ -1904,6 +1756,150 @@ bool ultrascan_port_pspec_update(UltraScanInfo *USI, HostScanStats *hss,
|
||||
return oldstate != newstate;
|
||||
}
|
||||
|
||||
/* Boost the scan delay for this host, usually because too many packet
|
||||
drops were detected. */
|
||||
void HostScanStats::boostScanDelay() {
|
||||
unsigned int maxAllowed = (USI->tcp_scan)? o.maxTCPScanDelay() : o.maxUDPScanDelay();
|
||||
if (sdn.delayms == 0)
|
||||
sdn.delayms = (USI->udp_scan)? 50 : 5; // In many cases, a pcap wait takes a minimum of 80ms, so this matters little :(
|
||||
else sdn.delayms = MIN(sdn.delayms * 2, MAX(sdn.delayms, 1000));
|
||||
sdn.delayms = MIN(sdn.delayms, maxAllowed);
|
||||
sdn.last_boost = USI->now;
|
||||
sdn.droppedRespSinceDelayChanged = 0;
|
||||
sdn.goodRespSinceDelayChanged = 0;
|
||||
}
|
||||
|
||||
/* Dismiss all probe attempts on bench -- the ports are marked
|
||||
'filtered' or whatever is appropriate for having no response */
|
||||
void HostScanStats::dismissBench() {
|
||||
int newstate;
|
||||
|
||||
if (probe_bench.empty()) return;
|
||||
newstate = scantype_no_response_means(USI->scantype);
|
||||
while(!probe_bench.empty()) {
|
||||
ultrascan_port_pspec_update(USI, this, &probe_bench.back(), newstate);
|
||||
probe_bench.pop_back();
|
||||
}
|
||||
bench_tryno = 0;
|
||||
}
|
||||
|
||||
/* Move all members of bench to retry_stack for probe retransmission */
|
||||
void HostScanStats::retransmitBench() {
|
||||
int newstate;
|
||||
if (probe_bench.empty()) return;
|
||||
|
||||
/* Move all contents of probe_bench to the end of retry_stack, updating retry_stack_tries accordingly */
|
||||
retry_stack.insert(retry_stack.end(), probe_bench.begin(), probe_bench.end());
|
||||
retry_stack_tries.insert(retry_stack_tries.end(), probe_bench.size(),
|
||||
bench_tryno);
|
||||
assert(retry_stack.size() == retry_stack_tries.size());
|
||||
probe_bench.erase(probe_bench.begin(), probe_bench.end());
|
||||
newstate = scantype_no_response_means(USI->scantype);
|
||||
bench_tryno = 0;
|
||||
}
|
||||
|
||||
/* Moves the given probe from the probes_outstanding list, to
|
||||
probe_bench, and decrements num_probes_waiting_retransmit
|
||||
accordingly */
|
||||
void HostScanStats::moveProbeToBench(list<UltraProbe *>::iterator probeI) {
|
||||
UltraProbe *probe = *probeI;
|
||||
if (!probe_bench.empty())
|
||||
assert(bench_tryno == probe->tryno);
|
||||
else {
|
||||
bench_tryno = probe->tryno;
|
||||
probe_bench.reserve(128);
|
||||
}
|
||||
probe_bench.push_back(*probe->pspec());
|
||||
probes_outstanding.erase(probeI);
|
||||
num_probes_waiting_retransmit--;
|
||||
delete probe;
|
||||
}
|
||||
|
||||
/* Undoes seq32_encode. Returns true if the checksum is correct and
|
||||
thus trynum was decoded properly. In that case, trynum (if not
|
||||
null) is filled with the decoded value. If pingseq is not null, it
|
||||
is filled with the scanping sequence number, which is 0 if this is
|
||||
not a ping. */
|
||||
|
||||
static bool seq32_decode(UltraScanInfo *USI, u32 seq, unsigned int *trynum,
|
||||
unsigned int *pingseq) {
|
||||
if (trynum) *trynum = 0;
|
||||
if (pingseq) *pingseq = 0;
|
||||
|
||||
/* Undo the mask xor */
|
||||
seq = seq ^ USI->seqmask;
|
||||
/* Check that both sides are the same */
|
||||
if ((seq >> 16) != (seq & 0xFFFF))
|
||||
return false;
|
||||
|
||||
if (trynum)
|
||||
*trynum = seq & 0xFF;
|
||||
|
||||
if (pingseq)
|
||||
*pingseq = (seq & 0xFF00) >> 8;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Sometimes the trynumber and/or pingseq are stored in a source
|
||||
portnumber of probes instead. This takes a port number in HOST
|
||||
BYTE ORDER. Returns true if the numbers seem reasonable, false if
|
||||
they are bogus. */
|
||||
static bool sport_decode(UltraScanInfo *USI, u16 portno, unsigned int *trynum,
|
||||
unsigned int *pingseq) {
|
||||
int tryval;
|
||||
tryval = portno - o.magic_port;
|
||||
if (tryval <= USI->perf.tryno_cap) {
|
||||
if (pingseq) *pingseq = 0;
|
||||
if (trynum) *trynum = tryval;
|
||||
} else {
|
||||
if (pingseq) *pingseq = tryval - USI->perf.tryno_cap;
|
||||
if (trynum) *trynum = 0;
|
||||
}
|
||||
if (tryval > USI->perf.tryno_cap + 256)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Called when a ping response is discovered. */
|
||||
static void ultrascan_ping_update(UltraScanInfo *USI, HostScanStats *hss,
|
||||
list<UltraProbe *>::iterator probeI,
|
||||
struct timeval *rcvdtime) {
|
||||
ultrascan_adjust_times(USI, hss, *probeI, rcvdtime);
|
||||
hss->destroyOutstandingProbe(probeI);
|
||||
}
|
||||
|
||||
|
||||
/* Called when a new status is determined for host in hss (eg. it is
|
||||
found to be up or down by a ping/ping_arp scan. The probe that led
|
||||
to this new decision is in probeI. This function needs to update
|
||||
timing information and other stats as appropriate.If rcvdtime is
|
||||
NULL, packet stats are not updated. */
|
||||
static void ultrascan_host_update(UltraScanInfo *USI, HostScanStats *hss,
|
||||
list<UltraProbe *>::iterator probeI,
|
||||
int newstate, struct timeval *rcvdtime) {
|
||||
UltraProbe *probe = *probeI;
|
||||
if (rcvdtime) ultrascan_adjust_times(USI, hss, probe, rcvdtime);
|
||||
|
||||
/* Adjust the target flags to note the new state. */
|
||||
if ((hss->target->flags & HOST_UP) == 0) {
|
||||
if (newstate == HOST_UP) {
|
||||
/* Clear any HOST_DOWN or HOST_FIREWALLED flags */
|
||||
hss->target->flags &= ~(HOST_DOWN|HOST_FIREWALLED);
|
||||
hss->target->flags |= HOST_UP;
|
||||
} else if (newstate == HOST_DOWN) {
|
||||
hss->target->flags &= ~HOST_FIREWALLED;
|
||||
hss->target->flags |= HOST_DOWN;
|
||||
} else assert(0);
|
||||
}
|
||||
|
||||
/* Kill outstanding probes */
|
||||
while(!hss->probes_outstanding.empty())
|
||||
hss->destroyOutstandingProbe(hss->probes_outstanding.begin());
|
||||
}
|
||||
|
||||
|
||||
/* This function is called when a new status is determined for a port.
|
||||
the port in the probeI of host hss is now in newstate. This
|
||||
function needs to update timing information, other stats, and the
|
||||
@@ -2276,7 +2272,7 @@ static void doAnyRetryStackRetransmits(UltraScanInfo *USI) {
|
||||
/* Sends a ping probe to the host. Assumes that caller has already
|
||||
checked that sending is OK w/congestion control and that pingprobe is
|
||||
available */
|
||||
void sendPingProbe(UltraScanInfo *USI, HostScanStats *hss) {
|
||||
static void sendPingProbe(UltraScanInfo *USI, HostScanStats *hss) {
|
||||
if (o.debugging > 1) {
|
||||
char tmpbuf[32];
|
||||
printf("Ultrascan PING SENT to %s [%s]\n", hss->target->targetipstr(),
|
||||
@@ -2413,7 +2409,7 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
|
||||
|
||||
/* Print occasional remaining time estimates, as well as
|
||||
debugging information */
|
||||
void printAnyStats(UltraScanInfo *USI) {
|
||||
static void printAnyStats(UltraScanInfo *USI) {
|
||||
|
||||
list<HostScanStats *>::iterator hostI;
|
||||
HostScanStats *hss;
|
||||
@@ -2665,7 +2661,7 @@ static bool do_one_select_round(UltraScanInfo *USI, struct timeval *stime) {
|
||||
match, or if matching seems to be broken for one reason or
|
||||
another. You can send in HBO or NBO, just as
|
||||
long as the two values are in the same byte order. */
|
||||
bool allow_ipid_match(u16 ipid_sent, u16 ipid_rcvd) {
|
||||
static bool allow_ipid_match(u16 ipid_sent, u16 ipid_rcvd) {
|
||||
static int numvalid = 0;
|
||||
static int numbogus = 0;
|
||||
|
||||
@@ -3220,7 +3216,7 @@ static void begin_sniffer(UltraScanInfo *USI, vector<Target *> &Targets) {
|
||||
|
||||
/* Go through the data structures, making appropriate changes (such as expiring
|
||||
probes, noting when hosts are complete, etc. */
|
||||
void processData(UltraScanInfo *USI) {
|
||||
static void processData(UltraScanInfo *USI) {
|
||||
list<HostScanStats *>::iterator hostI;
|
||||
list<UltraProbe *>::iterator probeI, nextProbeI;
|
||||
HostScanStats *host = NULL;
|
||||
@@ -3568,7 +3564,7 @@ void bounce_scan(Target *target, u16 *portarray, int numports,
|
||||
way got overloaded and dropped the last X packets, they are
|
||||
likely to get through (and flag us a problem if responsive)
|
||||
if we let them go first in the next round */
|
||||
void reverse_testing_order(struct portinfolist *pil, struct portinfo *scanarray) {
|
||||
static void reverse_testing_order(struct portinfolist *pil, struct portinfo *scanarray) {
|
||||
int currentidx, nextidx;
|
||||
struct portinfo *current;
|
||||
|
||||
|
||||
118
service_scan.cc
118
service_scan.cc
@@ -259,7 +259,6 @@ void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *mydata);
|
||||
void servicescan_write_handler(nsock_pool nsp, nsock_event nse, void *mydata);
|
||||
void servicescan_connect_handler(nsock_pool nsp, nsock_event nse, void *mydata);
|
||||
void end_svcprobe(nsock_pool nsp, enum serviceprobestate probe_state, ServiceGroup *SG, ServiceNFO *svc, nsock_iod nsi);
|
||||
int launchSomeServiceProbes(nsock_pool nsp, ServiceGroup *SG);
|
||||
|
||||
ServiceProbeMatch::ServiceProbeMatch() {
|
||||
deflineno = -1;
|
||||
@@ -1044,7 +1043,7 @@ void ServiceProbe::addMatch(const char *match, int lineno) {
|
||||
}
|
||||
|
||||
// Parses the given nmap-service-probes file into the AP class
|
||||
void parse_nmap_service_probe_file(AllProbes *AP, char *filename) {
|
||||
static void parse_nmap_service_probe_file(AllProbes *AP, char *filename) {
|
||||
ServiceProbe *newProbe;
|
||||
char line[2048];
|
||||
int lineno = 0;
|
||||
@@ -1137,6 +1136,17 @@ void parse_nmap_service_probes(AllProbes *AP) {
|
||||
parse_nmap_service_probe_file(AP, filename);
|
||||
}
|
||||
|
||||
static AllProbes *service_scan_init(void)
|
||||
{
|
||||
static AllProbes *AP;
|
||||
|
||||
if (AP) return AP;
|
||||
AP = new AllProbes();
|
||||
parse_nmap_service_probes(AP);
|
||||
|
||||
return AP;
|
||||
}
|
||||
|
||||
// If the buf (of length buflen) matches one of the regexes in this
|
||||
// ServiceProbe, returns the details of the match (service name,
|
||||
// version number if applicable, and whether this is a "soft" match.
|
||||
@@ -1892,6 +1902,52 @@ void end_svcprobe(nsock_pool nsp, enum serviceprobestate probe_state, ServiceGro
|
||||
return;
|
||||
}
|
||||
|
||||
// This function consults the ServiceGroup to determine whether any
|
||||
// more probes can be launched at this time. If so, it determines the
|
||||
// appropriate ones and then starts them up.
|
||||
static int launchSomeServiceProbes(nsock_pool nsp, ServiceGroup *SG) {
|
||||
ServiceNFO *svc;
|
||||
ServiceProbe *nextprobe;
|
||||
struct sockaddr_storage ss;
|
||||
size_t ss_len;
|
||||
|
||||
while (SG->services_in_progress.size() < SG->ideal_parallelism &&
|
||||
!SG->services_remaining.empty()) {
|
||||
// Start executing a probe from the new list and move it to in_progress
|
||||
svc = SG->services_remaining.front();
|
||||
if (svc->target->timedOut(nsock_gettimeofday())) {
|
||||
end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, NULL);
|
||||
continue;
|
||||
}
|
||||
nextprobe = svc->nextProbe(true);
|
||||
// We start by requesting a connection to the target
|
||||
if ((svc->niod = nsi_new(nsp, svc)) == NULL) {
|
||||
fatal("Failed to allocate Nsock I/O descriptor in launchSomeServiceProbes()");
|
||||
}
|
||||
if (o.debugging > 1) {
|
||||
printf("Starting probes against new service: %s:%hi (%s)\n", svc->target->targetipstr(), svc->portno, proto2ascii(svc->proto));
|
||||
}
|
||||
svc->target->TargetSockAddr(&ss, &ss_len);
|
||||
if (svc->proto == IPPROTO_TCP)
|
||||
nsock_connect_tcp(nsp, svc->niod, servicescan_connect_handler,
|
||||
DEFAULT_CONNECT_TIMEOUT, svc,
|
||||
(struct sockaddr *)&ss, ss_len,
|
||||
svc->portno);
|
||||
else {
|
||||
assert(svc->proto == IPPROTO_UDP);
|
||||
nsock_connect_udp(nsp, svc->niod, servicescan_connect_handler,
|
||||
svc, (struct sockaddr *) &ss, ss_len,
|
||||
svc->portno);
|
||||
}
|
||||
// Now remove it from the remaining service list
|
||||
SG->services_remaining.pop_front();
|
||||
// And add it to the in progress list
|
||||
SG->services_in_progress.push_back(svc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void servicescan_connect_handler(nsock_pool nsp, nsock_event nse, void *mydata) {
|
||||
nsock_iod nsi = nse_iod(nse);
|
||||
enum nse_status status = nse_status(nse);
|
||||
@@ -2172,8 +2228,7 @@ void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *mydata) {
|
||||
|
||||
// This is used in processResults to determine whether a FP
|
||||
// should be printed based on type of match, version intensity, etc.
|
||||
|
||||
int shouldWePrintFingerprint(ServiceNFO *svc) {
|
||||
static int shouldWePrintFingerprint(ServiceNFO *svc) {
|
||||
// Never print FP if hardmatched
|
||||
if (svc->probe_state == PROBESTATE_FINISHED_HARDMATCHED)
|
||||
return 0;
|
||||
@@ -2213,52 +2268,6 @@ list<ServiceNFO *>::iterator svc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function consults the ServiceGroup to determine whether any
|
||||
// more probes can be launched at this time. If so, it determines the
|
||||
// appropriate ones and then starts them up.
|
||||
int launchSomeServiceProbes(nsock_pool nsp, ServiceGroup *SG) {
|
||||
ServiceNFO *svc;
|
||||
ServiceProbe *nextprobe;
|
||||
struct sockaddr_storage ss;
|
||||
size_t ss_len;
|
||||
|
||||
while (SG->services_in_progress.size() < SG->ideal_parallelism &&
|
||||
!SG->services_remaining.empty()) {
|
||||
// Start executing a probe from the new list and move it to in_progress
|
||||
svc = SG->services_remaining.front();
|
||||
if (svc->target->timedOut(nsock_gettimeofday())) {
|
||||
end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, NULL);
|
||||
continue;
|
||||
}
|
||||
nextprobe = svc->nextProbe(true);
|
||||
// We start by requesting a connection to the target
|
||||
if ((svc->niod = nsi_new(nsp, svc)) == NULL) {
|
||||
fatal("Failed to allocate Nsock I/O descriptor in launchSomeServiceProbes()");
|
||||
}
|
||||
if (o.debugging > 1) {
|
||||
printf("Starting probes against new service: %s:%hi (%s)\n", svc->target->targetipstr(), svc->portno, proto2ascii(svc->proto));
|
||||
}
|
||||
svc->target->TargetSockAddr(&ss, &ss_len);
|
||||
if (svc->proto == IPPROTO_TCP)
|
||||
nsock_connect_tcp(nsp, svc->niod, servicescan_connect_handler,
|
||||
DEFAULT_CONNECT_TIMEOUT, svc,
|
||||
(struct sockaddr *)&ss, ss_len,
|
||||
svc->portno);
|
||||
else {
|
||||
assert(svc->proto == IPPROTO_UDP);
|
||||
nsock_connect_udp(nsp, svc->niod, servicescan_connect_handler,
|
||||
svc, (struct sockaddr *) &ss, ss_len,
|
||||
svc->portno);
|
||||
}
|
||||
// Now remove it from the remaining service list
|
||||
SG->services_remaining.pop_front();
|
||||
// And add it to the in progress list
|
||||
SG->services_in_progress.push_back(svc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Start the timeout clocks of any targets that have probes. Assumes
|
||||
that this is called before any probes have been launched (so they
|
||||
are all in services_remaining */
|
||||
@@ -2281,7 +2290,7 @@ static void startTimeOutClocks(ServiceGroup *SG) {
|
||||
// We iterate through SG->services_remaining and remove any with port/protocol
|
||||
// pairs that are excluded. We use AP->isExcluded() to determine which ports
|
||||
// are excluded.
|
||||
void remove_excluded_ports(AllProbes *AP, ServiceGroup *SG) {
|
||||
static void remove_excluded_ports(AllProbes *AP, ServiceGroup *SG) {
|
||||
list<ServiceNFO *>::iterator i, nxt;
|
||||
ServiceNFO *svc;
|
||||
|
||||
@@ -2311,7 +2320,7 @@ void remove_excluded_ports(AllProbes *AP, ServiceGroup *SG) {
|
||||
Targets specified. */
|
||||
int service_scan(vector<Target *> &Targets) {
|
||||
// int service_scan(Target *targets[], int num_targets)
|
||||
static AllProbes *AP;
|
||||
AllProbes *AP;
|
||||
ServiceGroup *SG;
|
||||
nsock_pool nsp;
|
||||
struct timeval now;
|
||||
@@ -2323,10 +2332,7 @@ int service_scan(vector<Target *> &Targets) {
|
||||
if (Targets.size() == 0)
|
||||
return 1;
|
||||
|
||||
if (!AP) {
|
||||
AP = new AllProbes();
|
||||
parse_nmap_service_probes(AP);
|
||||
}
|
||||
AP = service_scan_init();
|
||||
|
||||
|
||||
// Now I convert the targets into a new ServiceGroup
|
||||
|
||||
@@ -341,8 +341,5 @@ public:
|
||||
Targets specified. */
|
||||
int service_scan(std::vector<Target *> &Targets);
|
||||
|
||||
// Parses the given nmap-service-probes file into the AP class
|
||||
void parse_nmap_service_probe_file(AllProbes *AP, char *filename);
|
||||
|
||||
#endif /* SERVICE_SCAN_H */
|
||||
|
||||
|
||||
@@ -103,12 +103,14 @@
|
||||
#include "NmapOps.h"
|
||||
|
||||
extern NmapOps o;
|
||||
static int services_initialized = 0;
|
||||
static int numtcpports = 0;
|
||||
static int numudpports = 0;
|
||||
static struct service_list *service_table[SERVICE_TABLE_SIZE];
|
||||
|
||||
static int nmap_services_init() {
|
||||
static int services_initialized = 0;
|
||||
if (services_initialized) return 0;
|
||||
|
||||
char filename[512];
|
||||
FILE *fp;
|
||||
char servicename[128], proto[16];
|
||||
@@ -216,7 +218,6 @@ static int nmap_services_init() {
|
||||
struct servent *nmap_getservbyport(int port, const char *proto) {
|
||||
struct service_list *current;
|
||||
|
||||
if (!services_initialized)
|
||||
if (nmap_services_init() == -1)
|
||||
return NULL;
|
||||
|
||||
@@ -244,7 +245,6 @@ struct scan_lists *getdefaultports(int tcpscan, int udpscan) {
|
||||
int tcpportsneeded = 0;
|
||||
int udpportsneeded = 0;
|
||||
|
||||
if (!services_initialized)
|
||||
if (nmap_services_init() == -1)
|
||||
fatal("Getfastports: Couldn't get port numbers");
|
||||
|
||||
@@ -308,7 +308,6 @@ struct scan_lists *getfastports(int tcpscan, int udpscan) {
|
||||
int tcpportsneeded = 0;
|
||||
int udpportsneeded = 0;
|
||||
|
||||
if (!services_initialized)
|
||||
if (nmap_services_init() == -1)
|
||||
fatal("Getfastports: Couldn't get port numbers");
|
||||
|
||||
|
||||
1867
targets.cc
1867
targets.cc
File diff suppressed because it is too large
Load Diff
33
targets.h
33
targets.h
@@ -163,45 +163,12 @@ struct pingtech {
|
||||
};
|
||||
|
||||
|
||||
int get_ping_results(int sd, pcap_t *pd, Target *hostbatch[],
|
||||
int pingtype, struct timeval *time, struct pingtune *pt,
|
||||
struct timeout_info *to, int id, struct pingtech *ptech,
|
||||
struct scan_lists *ports);
|
||||
int sendpingqueries(int sd, int rawsd, eth_t *ethsd, Target *target,
|
||||
u16 seq, unsigned short id, struct scanstats *ss,
|
||||
struct timeval *time, int pingtype, struct pingtech ptech);
|
||||
int sendpingquery(int sd, int rawsd, eth_t *ethsd, Target *target,
|
||||
u16 seq, unsigned short id, struct scanstats *ss,
|
||||
struct timeval *time, int pingtype, struct pingtech ptech);
|
||||
int sendrawtcpudppingqueries(int rawsd, eth_t *ethsd, Target *target, int pingtype,
|
||||
u16 seq, struct timeval *time, struct pingtune *pt);
|
||||
int sendrawtcppingquery(int rawsd, struct eth_nfo *eth, Target *target, int pingtype, u16 probe_port,
|
||||
u16 seq, struct timeval *time, struct pingtune *pt);
|
||||
int sendrawudppingquery(int rawsd, struct eth_nfo *eth, Target *target, u16 probe_port,
|
||||
u16 seq, struct timeval *time, struct pingtune *pt);
|
||||
int sendconnecttcpqueries(Target *hostbatch[], struct tcpqueryinfo *tqi, Target *target,
|
||||
u16 seq, struct timeval *time, struct pingtune *pt, struct timeout_info *to, int max_sockets);
|
||||
int sendconnecttcpquery(Target *hostbatch[], struct tcpqueryinfo *tqi, Target *target, int probe_port_num,
|
||||
u16 seq, struct timeval *time, struct pingtune *pt, struct timeout_info *to, int max_sockets);
|
||||
int get_connecttcpscan_results(struct tcpqueryinfo *tqi,
|
||||
Target *hostbatch[],
|
||||
struct timeval *time, struct pingtune *pt,
|
||||
struct timeout_info *to);
|
||||
char *readhoststate(int state);
|
||||
void massping(Target *hostbatch[], int numhosts,
|
||||
struct scan_lists *ports, int pingtype);
|
||||
void hoststructfry(Target *hostbatch[], int nelem);
|
||||
/* Ports is the list of ports the user asked to be scanned (0 terminated),
|
||||
you can just pass NULL (it is only a stupid optimization that needs it) */
|
||||
Target *nexthost(HostGroupState *hs, TargetGroup *exclude_group,
|
||||
struct scan_lists *ports, int *pingtype);
|
||||
/* loads an exclude file into a excluded target list */
|
||||
TargetGroup* load_exclude(FILE *fExclude, char *szExclude);
|
||||
/* is the host we're passed in one that
|
||||
* should be excluded?
|
||||
*/
|
||||
int hostInExclude(struct sockaddr *checksock, size_t checksocklen,
|
||||
TargetGroup *exclude_group);
|
||||
/* a debugging routine to dump an exclude list to stdout. */
|
||||
int dumpExclude(TargetGroup*exclude_group);
|
||||
/* Returns the last host obtained by nexthost. It will be given again the next
|
||||
|
||||
473
tcpip.cc
473
tcpip.cc
@@ -256,156 +256,13 @@ void PacketTrace::traceArp(pdirection pdir, const u8 *frame, u32 len,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Takes an IP PACKET and prints it if packet tracing is enabled.
|
||||
'packet' must point to the IPv4 header. The direction must be
|
||||
PacketTrace::SENT or PacketTrace::RCVD . Optional 'now' argument
|
||||
makes this function slightly more efficient by avoiding a gettimeofday()
|
||||
call. */
|
||||
void PacketTrace::trace(pdirection pdir, const u8 *packet, u32 len,
|
||||
struct timeval *now) {
|
||||
struct timeval tv;
|
||||
|
||||
if (pdir == SENT) {
|
||||
PktCt.sendPackets++;
|
||||
PktCt.sendBytes += len;
|
||||
} else {
|
||||
PktCt.recvPackets++;
|
||||
PktCt.recvBytes += len;
|
||||
}
|
||||
|
||||
if (!o.packetTrace()) return;
|
||||
|
||||
if (now)
|
||||
tv = *now;
|
||||
else gettimeofday(&tv, NULL);
|
||||
|
||||
if (len < 20) {
|
||||
error("Packet tracer: tiny packet encountered");
|
||||
return;
|
||||
}
|
||||
|
||||
log_write(LOG_STDOUT|LOG_NORMAL, "%s (%.4fs) %s\n", (pdir == SENT)? "SENT" : "RCVD", o.TimeSinceStartMS(&tv) / 1000.0, ippackethdrinfo(packet, len));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Adds a trace entry when a connect() is attempted if packet tracing
|
||||
is enabled. Pass IPPROTO_TCP or IPPROTO_UDP as the protocol. The
|
||||
sock may be a sockaddr_in or sockaddr_in6. The return code of
|
||||
connect is passed in connectrc. If the return code is -1, get the
|
||||
errno and pass that as connect_errno. */
|
||||
void PacketTrace::traceConnect(u8 proto, const struct sockaddr *sock,
|
||||
int socklen, int connectrc, int connect_errno,
|
||||
const struct timeval *now) {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) sock;
|
||||
#if HAVE_IPV6
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sock;
|
||||
#endif
|
||||
struct timeval tv;
|
||||
char errbuf[64] = "";
|
||||
char targetipstr[INET6_ADDRSTRLEN] = "";
|
||||
u16 targetport = 0;
|
||||
|
||||
if (!o.packetTrace()) return;
|
||||
|
||||
if (now)
|
||||
tv = *now;
|
||||
else gettimeofday(&tv, NULL);
|
||||
|
||||
assert(proto == IPPROTO_TCP || proto == IPPROTO_UDP);
|
||||
|
||||
if (connectrc == 0)
|
||||
Strncpy(errbuf, "Connected", sizeof(errbuf));
|
||||
else {
|
||||
snprintf(errbuf, sizeof(errbuf), "%s", strerror(connect_errno));
|
||||
}
|
||||
|
||||
if (sin->sin_family == AF_INET) {
|
||||
if (inet_ntop(sin->sin_family, (char *) &sin->sin_addr, targetipstr,
|
||||
sizeof(targetipstr)) == NULL)
|
||||
fatal("Failed to convert target IPv4 address to presentation format!?!");
|
||||
targetport = ntohs(sin->sin_port);
|
||||
} else {
|
||||
#if HAVE_IPV6
|
||||
assert(sin->sin_family == AF_INET6);
|
||||
if (inet_ntop(sin->sin_family, (char *) &sin6->sin6_addr, targetipstr,
|
||||
sizeof(targetipstr)) == NULL)
|
||||
fatal("Failed to convert target IPv4 address to presentation format!?!");
|
||||
targetport = ntohs(sin6->sin6_port);
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
log_write(LOG_STDOUT|LOG_NORMAL, "CONN (%.4fs) %s localhost > %s:%d => %s\n",
|
||||
o.TimeSinceStartMS(&tv) / 1000.0,
|
||||
(proto == IPPROTO_TCP)? "TCP" : "UDP", targetipstr, targetport,
|
||||
errbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Converts an IP address given in a sockaddr_storage to an IPv4 or
|
||||
IPv6 IP address string. Since a static buffer is returned, this is
|
||||
not thread-safe and can only be used once in calls like printf()
|
||||
*/
|
||||
const char *inet_socktop(struct sockaddr_storage *ss) {
|
||||
static char buf[INET6_ADDRSTRLEN];
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) ss;
|
||||
#if HAVE_IPV6
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ss;
|
||||
#endif
|
||||
|
||||
if (inet_ntop(sin->sin_family, (sin->sin_family == AF_INET)?
|
||||
(char *) &sin->sin_addr :
|
||||
#if HAVE_IPV6
|
||||
(char *) &sin6->sin6_addr,
|
||||
#else
|
||||
(char *) NULL,
|
||||
#endif /* HAVE_IPV6 */
|
||||
buf, sizeof(buf)) == NULL) {
|
||||
fatal("Failed to convert target address to presentation format in inet_socktop!?! Error: %s", strerror(socket_errno()));
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Tries to resolve the given name (or literal IP) into a sockaddr
|
||||
structure. The af should be PF_INET (for IPv4) or PF_INET6. Returns 0
|
||||
if hostname cannot be resolved. It is OK to pass in a sockaddr_in or
|
||||
sockaddr_in6 casted to a sockaddr_storage as long as you use the matching
|
||||
pf.*/
|
||||
int resolve(char *hostname, struct sockaddr_storage *ss, size_t *sslen,
|
||||
int pf) {
|
||||
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result;
|
||||
int rc;
|
||||
|
||||
assert(ss);
|
||||
assert(sslen);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = pf;
|
||||
rc = getaddrinfo(hostname, NULL, &hints, &result);
|
||||
if (rc != 0)
|
||||
return 0;
|
||||
assert(result->ai_addrlen > 0 && result->ai_addrlen <= (int) sizeof(struct sockaddr_storage));
|
||||
*sslen = result->ai_addrlen;
|
||||
memcpy(ss, result->ai_addr, *sslen);
|
||||
freeaddrinfo(result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Returns a buffer of ASCII information about a packet that may look
|
||||
like "TCP 127.0.0.1:50923 > 127.0.0.1:3 S ttl=61 id=39516 iplen=40
|
||||
seq=625950769" or "ICMP PING (0/1) ttl=61 id=39516 iplen=40".
|
||||
Since this is a static buffer, don't use threads or call twice
|
||||
within (say) printf(). And certainly don't try to free() it! The
|
||||
returned buffer is NUL-terminated */
|
||||
const char *ippackethdrinfo(const u8 *packet, u32 len) {
|
||||
static const char *ippackethdrinfo(const u8 *packet, u32 len) {
|
||||
static char protoinfo[256];
|
||||
struct ip *ip = (struct ip *) packet;
|
||||
struct tcphdr *tcp;
|
||||
@@ -619,6 +476,148 @@ const char *ippackethdrinfo(const u8 *packet, u32 len) {
|
||||
return protoinfo;
|
||||
}
|
||||
|
||||
/* Takes an IP PACKET and prints it if packet tracing is enabled.
|
||||
'packet' must point to the IPv4 header. The direction must be
|
||||
PacketTrace::SENT or PacketTrace::RCVD . Optional 'now' argument
|
||||
makes this function slightly more efficient by avoiding a gettimeofday()
|
||||
call. */
|
||||
void PacketTrace::trace(pdirection pdir, const u8 *packet, u32 len,
|
||||
struct timeval *now) {
|
||||
struct timeval tv;
|
||||
|
||||
if (pdir == SENT) {
|
||||
PktCt.sendPackets++;
|
||||
PktCt.sendBytes += len;
|
||||
} else {
|
||||
PktCt.recvPackets++;
|
||||
PktCt.recvBytes += len;
|
||||
}
|
||||
|
||||
if (!o.packetTrace()) return;
|
||||
|
||||
if (now)
|
||||
tv = *now;
|
||||
else gettimeofday(&tv, NULL);
|
||||
|
||||
if (len < 20) {
|
||||
error("Packet tracer: tiny packet encountered");
|
||||
return;
|
||||
}
|
||||
|
||||
log_write(LOG_STDOUT|LOG_NORMAL, "%s (%.4fs) %s\n", (pdir == SENT)? "SENT" : "RCVD", o.TimeSinceStartMS(&tv) / 1000.0, ippackethdrinfo(packet, len));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Adds a trace entry when a connect() is attempted if packet tracing
|
||||
is enabled. Pass IPPROTO_TCP or IPPROTO_UDP as the protocol. The
|
||||
sock may be a sockaddr_in or sockaddr_in6. The return code of
|
||||
connect is passed in connectrc. If the return code is -1, get the
|
||||
errno and pass that as connect_errno. */
|
||||
void PacketTrace::traceConnect(u8 proto, const struct sockaddr *sock,
|
||||
int socklen, int connectrc, int connect_errno,
|
||||
const struct timeval *now) {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) sock;
|
||||
#if HAVE_IPV6
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sock;
|
||||
#endif
|
||||
struct timeval tv;
|
||||
char errbuf[64] = "";
|
||||
char targetipstr[INET6_ADDRSTRLEN] = "";
|
||||
u16 targetport = 0;
|
||||
|
||||
if (!o.packetTrace()) return;
|
||||
|
||||
if (now)
|
||||
tv = *now;
|
||||
else gettimeofday(&tv, NULL);
|
||||
|
||||
assert(proto == IPPROTO_TCP || proto == IPPROTO_UDP);
|
||||
|
||||
if (connectrc == 0)
|
||||
Strncpy(errbuf, "Connected", sizeof(errbuf));
|
||||
else {
|
||||
snprintf(errbuf, sizeof(errbuf), "%s", strerror(connect_errno));
|
||||
}
|
||||
|
||||
if (sin->sin_family == AF_INET) {
|
||||
if (inet_ntop(sin->sin_family, (char *) &sin->sin_addr, targetipstr,
|
||||
sizeof(targetipstr)) == NULL)
|
||||
fatal("Failed to convert target IPv4 address to presentation format!?!");
|
||||
targetport = ntohs(sin->sin_port);
|
||||
} else {
|
||||
#if HAVE_IPV6
|
||||
assert(sin->sin_family == AF_INET6);
|
||||
if (inet_ntop(sin->sin_family, (char *) &sin6->sin6_addr, targetipstr,
|
||||
sizeof(targetipstr)) == NULL)
|
||||
fatal("Failed to convert target IPv4 address to presentation format!?!");
|
||||
targetport = ntohs(sin6->sin6_port);
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
log_write(LOG_STDOUT|LOG_NORMAL, "CONN (%.4fs) %s localhost > %s:%d => %s\n",
|
||||
o.TimeSinceStartMS(&tv) / 1000.0,
|
||||
(proto == IPPROTO_TCP)? "TCP" : "UDP", targetipstr, targetport,
|
||||
errbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Converts an IP address given in a sockaddr_storage to an IPv4 or
|
||||
IPv6 IP address string. Since a static buffer is returned, this is
|
||||
not thread-safe and can only be used once in calls like printf()
|
||||
*/
|
||||
const char *inet_socktop(struct sockaddr_storage *ss) {
|
||||
static char buf[INET6_ADDRSTRLEN];
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) ss;
|
||||
#if HAVE_IPV6
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ss;
|
||||
#endif
|
||||
|
||||
if (inet_ntop(sin->sin_family, (sin->sin_family == AF_INET)?
|
||||
(char *) &sin->sin_addr :
|
||||
#if HAVE_IPV6
|
||||
(char *) &sin6->sin6_addr,
|
||||
#else
|
||||
(char *) NULL,
|
||||
#endif /* HAVE_IPV6 */
|
||||
buf, sizeof(buf)) == NULL) {
|
||||
fatal("Failed to convert target address to presentation format in inet_socktop!?! Error: %s", strerror(socket_errno()));
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Tries to resolve the given name (or literal IP) into a sockaddr
|
||||
structure. The af should be PF_INET (for IPv4) or PF_INET6. Returns 0
|
||||
if hostname cannot be resolved. It is OK to pass in a sockaddr_in or
|
||||
sockaddr_in6 casted to a sockaddr_storage as long as you use the matching
|
||||
pf.*/
|
||||
int resolve(char *hostname, struct sockaddr_storage *ss, size_t *sslen,
|
||||
int pf) {
|
||||
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result;
|
||||
int rc;
|
||||
|
||||
assert(ss);
|
||||
assert(sslen);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = pf;
|
||||
rc = getaddrinfo(hostname, NULL, &hints, &result);
|
||||
if (rc != 0)
|
||||
return 0;
|
||||
assert(result->ai_addrlen > 0 && result->ai_addrlen <= (int) sizeof(struct sockaddr_storage));
|
||||
*sslen = result->ai_addrlen;
|
||||
memcpy(ss, result->ai_addr, *sslen);
|
||||
freeaddrinfo(result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int islocalhost(const struct in_addr * const addr) {
|
||||
char dev[128];
|
||||
@@ -937,6 +936,87 @@ int send_tcp_raw( int sd, struct eth_nfo *eth, const struct in_addr *source,
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Create and send all fragments of a pre-built IPv4 packet
|
||||
* Minimal MTU for IPv4 is 68 and maximal IPv4 header size is 60
|
||||
* which gives us a right to cut TCP header after 8th byte
|
||||
* (shouldn't we inflate the header to 60 bytes too?) */
|
||||
int send_frag_ip_packet(int sd, struct eth_nfo *eth, u8 *packet,
|
||||
unsigned int packetlen, unsigned int mtu)
|
||||
{
|
||||
struct ip *ip = (struct ip *) packet;
|
||||
int headerlen = ip->ip_hl * 4; // better than sizeof(struct ip)
|
||||
unsigned int datalen = packetlen - headerlen;
|
||||
int fdatalen = 0, res = 0;
|
||||
|
||||
assert(headerlen <= (int) packetlen);
|
||||
assert(headerlen >= 20 && headerlen <= 60); // sanity check (RFC791)
|
||||
assert(mtu > 0 && mtu % 8 == 0); // otherwise, we couldn't set Fragment offset (ip->ip_off) correctly
|
||||
|
||||
if (datalen <= mtu) {
|
||||
error("Warning: fragmentation (mtu=%i) requested but the payload is too small already (%i)", mtu, datalen);
|
||||
return send_ip_packet(sd, eth, packet, packetlen);
|
||||
}
|
||||
|
||||
u8 *fpacket = (u8 *) safe_malloc(headerlen + mtu);
|
||||
memcpy(fpacket, packet, headerlen + mtu);
|
||||
ip = (struct ip *) fpacket;
|
||||
|
||||
// create fragments and send them
|
||||
for (int fragment = 1; fragment * mtu < datalen + mtu; fragment++) {
|
||||
fdatalen = (fragment * mtu <= datalen ? mtu : datalen % mtu);
|
||||
ip->ip_len = htons(headerlen + fdatalen);
|
||||
ip->ip_off = htons((fragment-1) * mtu / 8);
|
||||
if ((fragment-1) * mtu + fdatalen < datalen)
|
||||
ip->ip_off |= htons(IP_MF);
|
||||
#if HAVE_IP_IP_SUM
|
||||
ip->ip_sum = in_cksum((unsigned short *)ip, headerlen);
|
||||
#endif
|
||||
if (fragment > 1) // copy data payload
|
||||
memcpy(fpacket + headerlen, packet + headerlen + (fragment - 1) * mtu, fdatalen);
|
||||
res = send_ip_packet(sd, eth, fpacket, headerlen + fdatalen);
|
||||
if (res == -1)
|
||||
break;
|
||||
}
|
||||
free(fpacket);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int Sendto(char *functionname, int sd, const unsigned char *packet,
|
||||
int len, unsigned int flags, struct sockaddr *to, int tolen) {
|
||||
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) to;
|
||||
int res;
|
||||
int retries = 0;
|
||||
int sleeptime = 0;
|
||||
|
||||
do {
|
||||
if ((res = sendto(sd, (const char *) packet, len, flags, to, tolen)) == -1) {
|
||||
int err = socket_errno();
|
||||
|
||||
error("sendto in %s: sendto(%d, packet, %d, 0, %s, %d) => %s",
|
||||
functionname, sd, len, inet_ntoa(sin->sin_addr), tolen,
|
||||
strerror(err));
|
||||
#if WIN32
|
||||
return -1;
|
||||
#else
|
||||
if (retries > 2 || err == EPERM || err == EACCES || err == EADDRNOTAVAIL
|
||||
|| err == EINVAL)
|
||||
return -1;
|
||||
sleeptime = 15 * (1 << (2 * retries));
|
||||
error("Sleeping %d seconds then retrying", sleeptime);
|
||||
fflush(stderr);
|
||||
sleep(sleeptime);
|
||||
#endif
|
||||
}
|
||||
retries++;
|
||||
} while( res == -1);
|
||||
|
||||
PacketTrace::trace(PacketTrace::SENT, packet, len);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Send a pre-built IPv4 packet */
|
||||
int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetlen) {
|
||||
struct sockaddr_in sock;
|
||||
@@ -1007,53 +1087,6 @@ int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetl
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Create and send all fragments of a pre-built IPv4 packet
|
||||
* Minimal MTU for IPv4 is 68 and maximal IPv4 header size is 60
|
||||
* which gives us a right to cut TCP header after 8th byte
|
||||
* (shouldn't we inflate the header to 60 bytes too?) */
|
||||
int send_frag_ip_packet(int sd, struct eth_nfo *eth, u8 *packet,
|
||||
unsigned int packetlen, unsigned int mtu)
|
||||
{
|
||||
struct ip *ip = (struct ip *) packet;
|
||||
int headerlen = ip->ip_hl * 4; // better than sizeof(struct ip)
|
||||
unsigned int datalen = packetlen - headerlen;
|
||||
int fdatalen = 0, res = 0;
|
||||
|
||||
assert(headerlen <= (int) packetlen);
|
||||
assert(headerlen >= 20 && headerlen <= 60); // sanity check (RFC791)
|
||||
assert(mtu > 0 && mtu % 8 == 0); // otherwise, we couldn't set Fragment offset (ip->ip_off) correctly
|
||||
|
||||
if (datalen <= mtu) {
|
||||
error("Warning: fragmentation (mtu=%i) requested but the payload is too small already (%i)", mtu, datalen);
|
||||
return send_ip_packet(sd, eth, packet, packetlen);
|
||||
}
|
||||
|
||||
u8 *fpacket = (u8 *) safe_malloc(headerlen + mtu);
|
||||
memcpy(fpacket, packet, headerlen + mtu);
|
||||
ip = (struct ip *) fpacket;
|
||||
|
||||
// create fragments and send them
|
||||
for (int fragment = 1; fragment * mtu < datalen + mtu; fragment++) {
|
||||
fdatalen = (fragment * mtu <= datalen ? mtu : datalen % mtu);
|
||||
ip->ip_len = htons(headerlen + fdatalen);
|
||||
ip->ip_off = htons((fragment-1) * mtu / 8);
|
||||
if ((fragment-1) * mtu + fdatalen < datalen)
|
||||
ip->ip_off |= htons(IP_MF);
|
||||
#if HAVE_IP_IP_SUM
|
||||
ip->ip_sum = in_cksum((unsigned short *)ip, headerlen);
|
||||
#endif
|
||||
if (fragment > 1) // copy data payload
|
||||
memcpy(fpacket + headerlen, packet + headerlen + (fragment - 1) * mtu, fdatalen);
|
||||
res = send_ip_packet(sd, eth, fpacket, headerlen + fdatalen);
|
||||
if (res == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
free(fpacket);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Builds an ICMP packet (including an IP header) by packing the fields
|
||||
with the given information. It allocates a new buffer to store the
|
||||
packet contents, and then returns that buffer. The packet is not
|
||||
@@ -1113,19 +1146,6 @@ return build_ip_raw(source, victim, o.ttl, IPPROTO_ICMP, get_random_u16(),
|
||||
ping, icmplen, packetlen);
|
||||
}
|
||||
|
||||
void readippacket(const u8 *packet, int readdata) {
|
||||
struct ip *ip = (struct ip *) packet;
|
||||
switch(ip->ip_p) {
|
||||
case IPPROTO_UDP:
|
||||
readudppacket(packet, readdata);
|
||||
break;
|
||||
/* Should add ICMP here at some point */
|
||||
default:
|
||||
readtcppacket(packet, readdata);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* A simple function I wrote to help in debugging, shows the important fields
|
||||
of a TCP packet*/
|
||||
@@ -1659,7 +1679,9 @@ bool pcap_recv_timeval_valid() {
|
||||
with the given ip (ss) and mac address. An existing entry for the
|
||||
IP ss will be overwritten with the new MAC address. true is always
|
||||
returned for the set command. */
|
||||
bool NmapArpCache(int command, struct sockaddr_storage *ss, u8 *mac) {
|
||||
#define ARPCACHE_GET 1
|
||||
#define ARPCACHE_SET 2
|
||||
static bool NmapArpCache(int command, struct sockaddr_storage *ss, u8 *mac) {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) ss;
|
||||
struct ArpCache {
|
||||
u32 ip; /* Network byte order */
|
||||
@@ -1856,7 +1878,7 @@ int setTargetMACIfAvailable(Target *target, struct link_header *linkhdr,
|
||||
broadcast MAC address. The transmission is attempted up to 3
|
||||
times. If none of these elicit a response, false will be returned.
|
||||
If the mac is determined, true is returned. */
|
||||
bool doArp(const char *dev, const u8 *srcmac,
|
||||
static bool doArp(const char *dev, const u8 *srcmac,
|
||||
const struct sockaddr_storage *srcip,
|
||||
const struct sockaddr_storage *targetip, u8 *targetmac) {
|
||||
/* timeouts in microseconds ... the first ones are retransmit times, while
|
||||
@@ -2084,7 +2106,7 @@ struct dnet_collector_route_nfo {
|
||||
int numifaces;
|
||||
};
|
||||
|
||||
int collect_dnet_routes(const struct route_entry *entry, void *arg) {
|
||||
static int collect_dnet_routes(const struct route_entry *entry, void *arg) {
|
||||
struct dnet_collector_route_nfo *dcrn = (struct dnet_collector_route_nfo *) arg;
|
||||
int i;
|
||||
|
||||
@@ -2122,7 +2144,7 @@ int collect_dnet_routes(const struct route_entry *entry, void *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int collect_dnet_interfaces(const struct intf_entry *entry, void *arg) {
|
||||
static int collect_dnet_interfaces(const struct intf_entry *entry, void *arg) {
|
||||
struct dnet_collector_route_nfo *dcrn = (struct dnet_collector_route_nfo *) arg;
|
||||
int i;
|
||||
int numifaces = dcrn->numifaces;
|
||||
@@ -2840,41 +2862,6 @@ if (echots) *echots = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Sendto(char *functionname, int sd, const unsigned char *packet, int len,
|
||||
unsigned int flags, struct sockaddr *to, int tolen) {
|
||||
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) to;
|
||||
int res;
|
||||
int retries = 0;
|
||||
int sleeptime = 0;
|
||||
|
||||
do {
|
||||
if ((res = sendto(sd, (const char *) packet, len, flags, to, tolen)) == -1) {
|
||||
int err = socket_errno();
|
||||
|
||||
error("sendto in %s: sendto(%d, packet, %d, 0, %s, %d) => %s",
|
||||
functionname, sd, len, inet_ntoa(sin->sin_addr), tolen,
|
||||
strerror(err));
|
||||
#if WIN32
|
||||
return -1;
|
||||
#else
|
||||
if (retries > 2 || err == EPERM || err == EACCES || err == EADDRNOTAVAIL
|
||||
|| err == EINVAL)
|
||||
return -1;
|
||||
sleeptime = 15 * (1 << (2 * retries));
|
||||
error("Sleeping %d seconds then retrying", sleeptime);
|
||||
fflush(stderr);
|
||||
sleep(sleeptime);
|
||||
#endif
|
||||
}
|
||||
retries++;
|
||||
} while( res == -1);
|
||||
|
||||
PacketTrace::trace(PacketTrace::SENT, packet, len);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
IPProbe::IPProbe() {
|
||||
packetbuflen = 0;
|
||||
packetbuf = NULL;
|
||||
|
||||
38
tcpip.h
38
tcpip.h
@@ -629,11 +629,6 @@ u8 *build_ip_raw(const struct in_addr *source, const struct in_addr *victim,
|
||||
int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet,
|
||||
unsigned int packetlen);
|
||||
|
||||
/* Create and send all fragments of the pre-built packet */
|
||||
/* mtu = MTU - ipv4_headerlen */
|
||||
int send_frag_ip_packet(int sd, struct eth_nfo *eth, u8 *packet,
|
||||
unsigned int packetlen, unsigned int mtu);
|
||||
|
||||
/* Decoy versions of the raw packet sending functions ... */
|
||||
int send_tcp_raw_decoys( int sd, struct eth_nfo *eth,
|
||||
const struct in_addr *victim, int ttl,
|
||||
@@ -656,15 +651,6 @@ pcap_t *my_pcap_open_live(const char *device, int snaplen, int promisc,
|
||||
// invalid (Windows and Amiga), readip_pcap returns the time you called it.
|
||||
bool pcap_recv_timeval_valid();
|
||||
|
||||
/* Returns a buffer of ASCII information about a packet that may look
|
||||
like "TCP 127.0.0.1:50923 > 127.0.0.1:3 S ttl=61 id=39516 iplen=40
|
||||
seq=625950769" or "ICMP PING (0/1) ttl=61 id=39516 iplen=40".
|
||||
Since this is a static buffer, don't use threads or call twice
|
||||
within (say) printf(). And certainly don't try to free() it! The
|
||||
returned buffer is NUL-terminated */
|
||||
const char *ippackethdrinfo(const u8 *packet, u32 len);
|
||||
/* Shows the most important fields of an IP packet (including dissecting TCP/UDP headers. packet should point to the beginning of the IP header */
|
||||
void readippacket(const u8 *packet, int readdata);
|
||||
/* A simple function I wrote to help in debugging, shows the important fields
|
||||
of a TCP packet*/
|
||||
int readtcppacket(const u8 *packet, int readdata);
|
||||
@@ -726,8 +712,6 @@ bool setTargetNextHopMAC(Target *target);
|
||||
|
||||
int islocalhost(const struct in_addr * const addr);
|
||||
int unblock_socket(int sd);
|
||||
int Sendto(char *functionname, int sd, const unsigned char *packet, int len,
|
||||
unsigned int flags, struct sockaddr *to, int tolen);
|
||||
|
||||
// Takes a protocol number like IPPROTO_TCP, IPPROTO_UDP, or
|
||||
// IPPROTO_TCP and returns a ascii representation (or "unknown" if it
|
||||
@@ -744,19 +728,6 @@ int get_link_offset(char *device);
|
||||
char *readip_pcap(pcap_t *pd, unsigned int *len, long to_usec,
|
||||
struct timeval *rcvdtime, struct link_header *linknfo);
|
||||
|
||||
/* A trivial functon that maintains a cache of IP to MAC Address
|
||||
entries. If the command is ARPCACHE_GEt, this func looks for the
|
||||
IPv4 address in ss and fills in the 'mac' parameter and returns
|
||||
true if it is found. Otherwise (not found), the function returns
|
||||
false. If the command is ARPCACHE_SET, the function adds an entry
|
||||
with the given ip (ss) and mac address. An existing entry for the
|
||||
IP ss will be overwritten with the new MAC address. true is always
|
||||
returned for the set command. */
|
||||
#define ARPCACHE_GET 1
|
||||
#define ARPCACHE_SET 2
|
||||
bool NmapArpCache(int command, struct sockaddr_storage *ss, u8 *mac);
|
||||
|
||||
|
||||
/* Attempts to read one IPv4/Ethernet ARP reply packet from the pcap
|
||||
descriptor pd. If it receives one, fills in sendermac (must pass
|
||||
in 6 bytes), senderIP, and rcvdtime (can be NULL if you don't care)
|
||||
@@ -767,15 +738,6 @@ bool NmapArpCache(int command, struct sockaddr_storage *ss, u8 *mac);
|
||||
int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac, struct in_addr *senderIP,
|
||||
long to_usec, struct timeval *rcvdtime);
|
||||
|
||||
/* Issues an ARP request for the MAC of targetss (which will be placed
|
||||
in targetmac if obtained) from the source IP (srcip) and source mac
|
||||
(srcmac) given. "The request is ussued using device dev to the
|
||||
broadcast MAC address. The transmission is attempted up to 3
|
||||
times. If none of these elicit a response, false will be returned.
|
||||
If the mac is determined, true is returned. */
|
||||
bool doArp(const char *dev, u8 *srcmac, struct sockaddr_storage *srcip,
|
||||
struct sockaddr_storage *targetip, u8 *targetmac);
|
||||
|
||||
#ifndef HAVE_INET_ATON
|
||||
int inet_aton(register const char *, struct in_addr *);
|
||||
#endif
|
||||
|
||||
66
tty.cc
66
tty.cc
@@ -127,7 +127,7 @@ extern NmapOps o;
|
||||
// Microsoft's runtime makes this fairly simple. :)
|
||||
void tty_init() { return; }
|
||||
static int tty_getchar() { return _kbhit() ? getch() : -1; }
|
||||
void tty_done() { return; }
|
||||
static void tty_done() { return; }
|
||||
|
||||
#else
|
||||
#if !defined(O_NONBLOCK) && defined(O_NDELAY)
|
||||
@@ -146,33 +146,6 @@ extern int tcsetattr(int fd, int actions, struct termios *termios_p);
|
||||
static int tty_fd = 0;
|
||||
static struct termios saved_ti;
|
||||
|
||||
void tty_init()
|
||||
{
|
||||
int fd;
|
||||
struct termios ti;
|
||||
|
||||
if ((fd = open("/dev/tty", O_RDONLY | O_NONBLOCK)) < 0) return;
|
||||
|
||||
#ifndef __CYGWIN32__
|
||||
if (tcgetpgrp(fd) != getpid()) {
|
||||
close(fd); return;
|
||||
}
|
||||
#endif
|
||||
|
||||
tcgetattr(fd, &ti);
|
||||
if (tty_fd == 0)
|
||||
saved_ti = ti;
|
||||
ti.c_lflag &= ~(ICANON | ECHO);
|
||||
ti.c_cc[VMIN] = 1;
|
||||
ti.c_cc[VTIME] = 0;
|
||||
tcsetattr(fd, TCSANOW, &ti);
|
||||
|
||||
if (tty_fd == 0)
|
||||
tty_fd = fd;
|
||||
|
||||
atexit(tty_done);
|
||||
}
|
||||
|
||||
static int tty_getchar()
|
||||
{
|
||||
int c, numChars;
|
||||
@@ -200,7 +173,7 @@ static int tty_getchar()
|
||||
return -1;
|
||||
}
|
||||
|
||||
void tty_done()
|
||||
static void tty_done()
|
||||
{
|
||||
int fd;
|
||||
|
||||
@@ -212,14 +185,45 @@ void tty_done()
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes the terminal for unbuffered non-blocking input. Also
|
||||
* registers tty_done() via atexit(). You need to call this before
|
||||
* you ever call keyWasPressed().
|
||||
*/
|
||||
void tty_init()
|
||||
{
|
||||
int fd;
|
||||
struct termios ti;
|
||||
|
||||
if ((fd = open("/dev/tty", O_RDONLY | O_NONBLOCK)) < 0) return;
|
||||
|
||||
#ifndef __CYGWIN32__
|
||||
if (tcgetpgrp(fd) != getpid()) {
|
||||
close(fd); return;
|
||||
}
|
||||
#endif
|
||||
|
||||
tcgetattr(fd, &ti);
|
||||
if (tty_fd == 0)
|
||||
saved_ti = ti;
|
||||
ti.c_lflag &= ~(ICANON | ECHO);
|
||||
ti.c_cc[VMIN] = 1;
|
||||
ti.c_cc[VTIME] = 0;
|
||||
tcsetattr(fd, TCSANOW, &ti);
|
||||
|
||||
if (tty_fd == 0)
|
||||
tty_fd = fd;
|
||||
|
||||
atexit(tty_done);
|
||||
}
|
||||
|
||||
#endif //!win32
|
||||
|
||||
/* This is the best method here. It will catch all of the predefined
|
||||
/* Catches all of the predefined
|
||||
keypresses and interpret them, and it will also tell you if you
|
||||
should print anything. A value of true being returned means a
|
||||
nonstandard key has been pressed and the calling method should
|
||||
print a status message */
|
||||
|
||||
bool keyWasPressed()
|
||||
{
|
||||
int c;
|
||||
|
||||
16
tty.h
16
tty.h
@@ -97,15 +97,15 @@
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Initializes the terminal for unbuffered non-blocking input. Also registers
|
||||
* tty_done() via atexit().
|
||||
* Initializes the terminal for unbuffered non-blocking input. Also
|
||||
* registers tty_done() via atexit(). You need to call this before
|
||||
* you ever call keyWasPressed().
|
||||
*/
|
||||
void tty_init();
|
||||
|
||||
/*
|
||||
* Restores the terminal parameters and closes the file descriptor.
|
||||
*/
|
||||
void tty_done();
|
||||
|
||||
/* This is the best method here. It will catch all of the predefined keypresses and interpret them, and it will also tell you if you should print anything. A value of true being returned means a nonstandard key has been pressed and the calling method should print a status message */
|
||||
/* Catches all of the predefined keypresses and interpret them, and it
|
||||
will also tell you if you should print anything. A value of true
|
||||
being returned means a nonstandard key has been pressed and the
|
||||
calling method should print a status message */
|
||||
bool keyWasPressed();
|
||||
|
||||
|
||||
65
utils.cc
65
utils.cc
@@ -371,71 +371,6 @@ int Send(int sd, const void *msg, size_t len, int flags) {
|
||||
return (res < 0)? -1 : (int) len;
|
||||
}
|
||||
|
||||
// Write data to a file descriptor, keep retrying until an error or the full length
|
||||
// is written. Returns -1 if there is an error, or len if the full length was sent.
|
||||
// Note that this does NOT work well on Windows using sockets -- so use Send() above
|
||||
// for those. I don't know if it works with regular files on Windows with files).
|
||||
ssize_t Write(int fd, const void *buf, size_t count) {
|
||||
int res;
|
||||
unsigned int len;
|
||||
|
||||
len = 0;
|
||||
do {
|
||||
res = write(fd,(char *) buf + len,count - len);
|
||||
if (res > 0)
|
||||
len += res;
|
||||
} while(len < count && (res != -1 || socket_errno() == EINTR));
|
||||
|
||||
return (res == -1)? -1 : (int) count;
|
||||
}
|
||||
|
||||
|
||||
/* gcd_1 and gcd_n_long were sent in by Peter Kosinar <goober@gjh.sk>
|
||||
Not needed for gcd_n_long, just for the case you'd want to have gcd
|
||||
for two arguments too. */
|
||||
unsigned long gcd_ulong(unsigned long a, unsigned long b)
|
||||
{
|
||||
/* Shorter
|
||||
while (b) { a%=b; if (!a) return b; b%=a; } */
|
||||
|
||||
/* Faster */
|
||||
unsigned long c;
|
||||
if (a<b) { c=a; a=b; b=c; }
|
||||
while (b) { c=a%b; a=b; b=c; }
|
||||
|
||||
/* Common for both */
|
||||
return a;
|
||||
}
|
||||
|
||||
unsigned long gcd_n_ulong(long nvals, unsigned long *val)
|
||||
{
|
||||
unsigned long a,b,c;
|
||||
|
||||
if (!nvals) return 1;
|
||||
a=*val;
|
||||
for (nvals--;nvals;nvals--)
|
||||
{
|
||||
b=*++val;
|
||||
if (a<b) { c=a; a=b; b=c; }
|
||||
while (b) { c=a%b; a=b; b=c; }
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
unsigned int gcd_uint(unsigned int a, unsigned int b)
|
||||
{
|
||||
/* Shorter
|
||||
while (b) { a%=b; if (!a) return b; b%=a; } */
|
||||
|
||||
/* Faster */
|
||||
unsigned int c;
|
||||
if (a<b) { c=a; a=b; b=c; }
|
||||
while (b) { c=a%b; a=b; b=c; }
|
||||
|
||||
/* Common for both */
|
||||
return a;
|
||||
}
|
||||
|
||||
unsigned int gcd_n_uint(int nvals, unsigned int *val)
|
||||
{
|
||||
unsigned int a,b,c;
|
||||
|
||||
5
utils.h
5
utils.h
@@ -207,11 +207,6 @@ char *chomp(char *string);
|
||||
// is sent. Returns -1 if there is an error, or len if the full length was sent.
|
||||
int Send(int sd, const void *msg, size_t len, int flags);
|
||||
|
||||
ssize_t Write(int fd, const void *buf, size_t count);
|
||||
|
||||
unsigned long gcd_ulong(unsigned long a, unsigned long b);
|
||||
unsigned int gcd_uint(unsigned int a, unsigned int b);
|
||||
unsigned long gcd_n_ulong(long nvals, unsigned long *val);
|
||||
unsigned int gcd_n_uint(int nvals, unsigned int *val);
|
||||
|
||||
int arg_parse(const char *command, char ***argv);
|
||||
|
||||
Reference in New Issue
Block a user