mirror of
https://github.com/nmap/nmap.git
synced 2025-12-17 13:09:02 +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-*-
|
# 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
|
Nmap 4.02ALPHA1
|
||||||
|
|
||||||
o Added the --log-errors option, which causes most warnings and error
|
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;
|
struct MAC_entry **table;
|
||||||
} MacTable;
|
} MacTable;
|
||||||
|
|
||||||
static int initialized = 0;
|
|
||||||
|
|
||||||
static inline int MacCharPrefix2Key(const u8 *prefix) {
|
static inline int MacCharPrefix2Key(const u8 *prefix) {
|
||||||
return (prefix[0] << 16) + (prefix[1] << 8) + prefix[2];
|
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;
|
return prefix % table_capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeTable() {
|
void mac_prefix_init() {
|
||||||
|
static int initialized = 0;
|
||||||
if (initialized) return;
|
if (initialized) return;
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
char filename[256];
|
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);
|
int pos = MACTableHash(prefix, MacTable.table_capacity);
|
||||||
|
|
||||||
while (MacTable.table[pos]) {
|
while (MacTable.table[pos]) {
|
||||||
@@ -216,7 +215,7 @@ const char *MACPrefix2Corp(const u8 *prefix) {
|
|||||||
struct MAC_entry *ent;
|
struct MAC_entry *ent;
|
||||||
|
|
||||||
if (!prefix) fatal("MACPrefix2Corp called with a NULL prefix");
|
if (!prefix) fatal("MACPrefix2Corp called with a NULL prefix");
|
||||||
if (!initialized) InitializeTable();
|
mac_prefix_init();
|
||||||
|
|
||||||
ent = findMACEntry(MacCharPrefix2Key(prefix));
|
ent = findMACEntry(MacCharPrefix2Key(prefix));
|
||||||
return (ent)? ent->vendor : NULL;
|
return (ent)? ent->vendor : NULL;
|
||||||
@@ -231,7 +230,7 @@ const char *MACPrefix2Corp(const u8 *prefix) {
|
|||||||
bool MACCorp2Prefix(const char *vendorstr, u8 *mac_data) {
|
bool MACCorp2Prefix(const char *vendorstr, u8 *mac_data) {
|
||||||
if (!vendorstr) fatal("%s: vendorstr is NULL", __FUNCTION__);
|
if (!vendorstr) fatal("%s: vendorstr is NULL", __FUNCTION__);
|
||||||
if (!mac_data) fatal("%s: mac_data 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++ ) {
|
for(int i = 0; i < MacTable.table_capacity; i++ ) {
|
||||||
if (MacTable.table[i])
|
if (MacTable.table[i])
|
||||||
|
|||||||
@@ -107,11 +107,13 @@ static char *charpool[16];
|
|||||||
static int currentcharpool;
|
static int currentcharpool;
|
||||||
static int currentcharpoolsz;
|
static int currentcharpoolsz;
|
||||||
static char *nextchar;
|
static char *nextchar;
|
||||||
static int charpool_initialized = 0;
|
|
||||||
|
|
||||||
#define ALIGN_ON sizeof(char *)
|
#define ALIGN_ON sizeof(char *)
|
||||||
|
|
||||||
static int cp_init(void) {
|
static int cp_init(void) {
|
||||||
|
static int charpool_initialized = 0;
|
||||||
|
if (charpool_initialized) return 0;
|
||||||
|
|
||||||
/* Create our char pool */
|
/* Create our char pool */
|
||||||
currentcharpool = 0;
|
currentcharpool = 0;
|
||||||
currentcharpoolsz = 16384;
|
currentcharpoolsz = 16384;
|
||||||
@@ -135,7 +137,7 @@ void *cp_alloc(int sz) {
|
|||||||
char *p;
|
char *p;
|
||||||
int modulus;
|
int modulus;
|
||||||
|
|
||||||
if (!charpool_initialized) cp_init();
|
cp_init();
|
||||||
|
|
||||||
if ((modulus = sz % ALIGN_ON))
|
if ((modulus = sz % ALIGN_ON))
|
||||||
sz += ALIGN_ON - modulus;
|
sz += ALIGN_ON - modulus;
|
||||||
@@ -159,7 +161,6 @@ char *q;
|
|||||||
char *end;
|
char *end;
|
||||||
int modulus;
|
int modulus;
|
||||||
|
|
||||||
if (!charpool_initialized)
|
|
||||||
cp_init();
|
cp_init();
|
||||||
|
|
||||||
end = charpool[currentcharpool] + currentcharpoolsz;
|
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 --
|
Proxy timing is adjusted, but proxy->latestid is NOT ADJUSTED --
|
||||||
you'll have to do that yourself. Probes_sent is set to the number
|
you'll have to do that yourself. Probes_sent is set to the number
|
||||||
of probe packets sent during execution */
|
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) {
|
int *probes_rcvd) {
|
||||||
struct timeval tv_end;
|
struct timeval tv_end;
|
||||||
int tries = 0;
|
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
|
one, assuming the given IPID Sequencing class. Returns -1 if the
|
||||||
distance cannot be determined */
|
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)
|
if (seqclass == IPID_SEQ_INCR)
|
||||||
return endid - startid;
|
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
|
proxy is determined to be unsuitable, the function whines and exits
|
||||||
the program */
|
the program */
|
||||||
#define NUM_IPID_PROBES 6
|
#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) {
|
const struct in_addr *first_target) {
|
||||||
int probes_sent = 0, probes_returned = 0;
|
int probes_sent = 0, probes_returned = 0;
|
||||||
int hardtimeout = 9000000; /* Generally don't wait more than 9 secs total */
|
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;
|
proxy->ethptr = &proxy->eth;
|
||||||
} else {
|
} else {
|
||||||
if ((proxy->rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )
|
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);
|
unblock_socket(proxy->rawsd);
|
||||||
broadcast_socket(proxy->rawsd);
|
broadcast_socket(proxy->rawsd);
|
||||||
#ifndef WIN32
|
#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
|
count of 'testcount' while the 'realcount' is as given. If the
|
||||||
testcount was correct, timing is made more aggressive, while it is
|
testcount was correct, timing is made more aggressive, while it is
|
||||||
slowed down in the case of an error */
|
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,
|
Target *target, int testcount,
|
||||||
int realcount) {
|
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
|
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 */
|
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,
|
Target *target, u16 *ports, int numports,
|
||||||
struct timeval *sent_time, struct timeval *rcv_time)
|
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 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
|
the number of open ports in the given list. Under the covers, this
|
||||||
function just farms out the hard work to another function */
|
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,
|
Target *target, u16 *ports, int numports,
|
||||||
struct timeval *sent_time, struct timeval *rcv_time) {
|
struct timeval *sent_time, struct timeval *rcv_time) {
|
||||||
int tries = 0;
|
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
|
/* Recursively Idlescans scans a group of ports using a depth-first
|
||||||
divide-and-conquer strategy to find the open one(s) */
|
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) {
|
u16 *ports, int numports, int expectedopen) {
|
||||||
|
|
||||||
int firstHalfSz = (numports + 1)/2;
|
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;
|
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[]) {
|
int nmap_main(int argc, char *argv[]) {
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
int i, arg;
|
int i, arg;
|
||||||
@@ -1629,98 +1863,6 @@ struct scan_lists *getpts(char *origexpr) {
|
|||||||
return ports;
|
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() {
|
void printinteractiveusage() {
|
||||||
printf(
|
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 */
|
/* Just a routine for obtaining a string for printing based on the scantype */
|
||||||
char *scantype2str(stype scantype) {
|
char *scantype2str(stype scantype) {
|
||||||
@@ -2147,6 +2148,13 @@ void sigdie(int signo) {
|
|||||||
exit(1);
|
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) {
|
int nmap_fetchfile(char *filename_returned, int bufferlen, char *file) {
|
||||||
char *dirptr;
|
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**********************************/
|
/***********************PROTOTYPES**********************************/
|
||||||
|
|
||||||
/* print usage information and exit */
|
|
||||||
void printusage(char *name, int rc);
|
|
||||||
/* print Interactive usage information */
|
/* print Interactive usage information */
|
||||||
void printinteractiveusage();
|
void printinteractiveusage();
|
||||||
|
|
||||||
@@ -454,7 +452,6 @@ int listen_icmp(int icmpsock, unsigned short outports[],
|
|||||||
int nmap_main(int argc, char *argv[]);
|
int nmap_main(int argc, char *argv[]);
|
||||||
|
|
||||||
/* general helper functions */
|
/* general helper functions */
|
||||||
char *grab_next_host_spec(FILE *inputfd, int argc, char **fakeargv);
|
|
||||||
int parse_targets(struct targets *targets, char *h);
|
int parse_targets(struct targets *targets, char *h);
|
||||||
char *statenum2str(int state);
|
char *statenum2str(int state);
|
||||||
char *scantype2str(stype scantype);
|
char *scantype2str(stype scantype);
|
||||||
@@ -469,7 +466,6 @@ char *tsseqclass2ascii(int seqclass);
|
|||||||
into a difficulty string like "Worthy Challenge */
|
into a difficulty string like "Worthy Challenge */
|
||||||
const char *seqidx2difficultystr(unsigned long idx);
|
const char *seqidx2difficultystr(unsigned long idx);
|
||||||
int nmap_fetchfile(char *filename_returned, int bufferlen, char *file);
|
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);
|
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 */
|
/* 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
|
// In milliseconds
|
||||||
// Each row MUST be terminated with -1
|
// Each row MUST be terminated with -1
|
||||||
int read_timeouts[][4] = {
|
static int read_timeouts[][4] = {
|
||||||
{ 4000, 4000, 5000, -1 }, // 1 server
|
{ 4000, 4000, 5000, -1 }, // 1 server
|
||||||
{ 2500, 4000, -1, -1 }, // 2 servers
|
{ 2500, 4000, -1, -1 }, // 2 servers
|
||||||
{ 2500, 3000, -1, -1 }, // 3+ servers
|
{ 2500, 3000, -1, -1 }, // 3+ servers
|
||||||
@@ -275,7 +275,6 @@ static std::list<request *> cname_reqs;
|
|||||||
static int total_reqs;
|
static int total_reqs;
|
||||||
static nsock_pool dnspool=NULL;
|
static nsock_pool dnspool=NULL;
|
||||||
|
|
||||||
static int etchosts_filled=0;
|
|
||||||
static std::list<host_elem *> etchosts[HASH_TABLE_SIZE];
|
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;
|
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 ---------------------
|
//------------------- Prototypes and macros ---------------------
|
||||||
|
|
||||||
void close_dns_servers();
|
void put_dns_packet_on_wire(request *req);
|
||||||
void write_evt_handler(nsock_pool nsp, nsock_event evt, void *req_v);
|
|
||||||
void do_possible_writes();
|
|
||||||
int deal_with_timedout_reads();
|
|
||||||
|
|
||||||
#define ACTION_FINISHED 0
|
#define ACTION_FINISHED 0
|
||||||
#define ACTION_CNAME_LIST 1
|
#define ACTION_CNAME_LIST 1
|
||||||
@@ -301,7 +297,7 @@ int deal_with_timedout_reads();
|
|||||||
|
|
||||||
//------------------- Misc code ---------------------
|
//------------------- Misc code ---------------------
|
||||||
|
|
||||||
void output_summary() {
|
static void output_summary() {
|
||||||
int tp = stat_ok + stat_nx + stat_dropped;
|
int tp = stat_ok + stat_nx + stat_dropped;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
|
|
||||||
@@ -314,22 +310,206 @@ void output_summary() {
|
|||||||
(unsigned long) servs.size(), stat_ok, stat_nx, stat_dropped, stat_sf, stat_trans);
|
(unsigned long) servs.size(), stat_ok, stat_nx, stat_dropped, stat_sf, stat_trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void check_capacities(dns_server *tpserv) {
|
||||||
void check_capacities(dns_server *tpserv) {
|
|
||||||
if (tpserv->capacity < CAPACITY_MIN) tpserv->capacity = CAPACITY_MIN;
|
if (tpserv->capacity < CAPACITY_MIN) tpserv->capacity = CAPACITY_MIN;
|
||||||
if (tpserv->capacity > CAPACITY_MAX) tpserv->capacity = CAPACITY_MAX;
|
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);
|
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
|
// After processing a DNS response, we search through the IPs we're
|
||||||
// looking for and update their results as necessary.
|
// looking for and update their results as necessary.
|
||||||
// Returns non-zero if this matches a query we're looking for
|
// 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<dns_server *>::iterator servI;
|
||||||
std::list<request *>::iterator reqI;
|
std::list<request *>::iterator reqI;
|
||||||
dns_server *tpserv;
|
dns_server *tpserv;
|
||||||
@@ -381,7 +561,7 @@ int process_result(u32 ia, char *result, int action, u16 id) {
|
|||||||
// encoded string inside a packet.
|
// encoded string inside a packet.
|
||||||
// maxlen is the very maximum length (in total bytes)
|
// maxlen is the very maximum length (in total bytes)
|
||||||
// that should be processed
|
// 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;
|
u32 ip=0;
|
||||||
int i, j;
|
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
|
// 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.
|
// 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 *nameloc) {
|
||||||
int compression=0;
|
int compression=0;
|
||||||
|
|
||||||
@@ -458,10 +638,9 @@ int advance_past_dns_name(u8 *buf, int buflen, int curbuf,
|
|||||||
else return curbuf+1;
|
else return curbuf+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Nsock read handler. One nsock read for each DNS server exists at each
|
// Nsock read handler. One nsock read for each DNS server exists at each
|
||||||
// time. This function uses various helper functions as defined above.
|
// 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;
|
u8 *buf;
|
||||||
int buflen, curbuf=0;
|
int buflen, curbuf=0;
|
||||||
int i, nameloc, rdlen, atype, aclass;
|
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...
|
// 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
|
// Adds DNS servers to the dns_server list. They can be separated by
|
||||||
// commas or spaces - NOTE this doesn't actually do any connecting!
|
// 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;
|
std::list<dns_server *>::iterator servI;
|
||||||
dns_server *tpserv;
|
dns_server *tpserv;
|
||||||
char *hostname;
|
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
|
#ifdef WIN32
|
||||||
void win32_read_registry(char *controlset) {
|
void win32_read_registry(char *controlset) {
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
@@ -921,7 +894,7 @@ void win32_read_registry(char *controlset) {
|
|||||||
|
|
||||||
// Parses /etc/resolv.conf (unix) or the registry (win32) and adds
|
// Parses /etc/resolv.conf (unix) or the registry (win32) and adds
|
||||||
// all the nameservers found via the add_dns_server() function.
|
// all the nameservers found via the add_dns_server() function.
|
||||||
void parse_resolvdotconf() {
|
static void parse_resolvdotconf() {
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
|
|
||||||
@@ -956,7 +929,7 @@ void parse_resolvdotconf() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void parse_etchosts(char *fname) {
|
static void parse_etchosts(char *fname) {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char buf[2048], hname[256], ipaddrstr[16], *tp;
|
char buf[2048], hname[256], ipaddrstr[16], *tp;
|
||||||
struct in_addr ia;
|
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;
|
std::list<host_elem *>::iterator hostI;
|
||||||
host_elem *tpelem;
|
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 ---------------------
|
//------------------- Main loops ---------------------
|
||||||
|
|
||||||
|
|
||||||
// Actual main loop
|
// 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;
|
Target **hostI;
|
||||||
std::list<request *>::iterator reqI;
|
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 necessary, set up the /etc/hosts hashtable
|
||||||
if (etchosts_filled == 0) {
|
etchosts_init();
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
total_reqs = 0;
|
total_reqs = 0;
|
||||||
|
|||||||
12
nmap_rpc.cc
12
nmap_rpc.cc
@@ -106,7 +106,6 @@
|
|||||||
#include "NmapOps.h"
|
#include "NmapOps.h"
|
||||||
|
|
||||||
extern NmapOps o;
|
extern NmapOps o;
|
||||||
static int services_initialized = 0;
|
|
||||||
static struct rpc_info ri;
|
static struct rpc_info ri;
|
||||||
static int udp_rpc_socket = -1;
|
static int udp_rpc_socket = -1;
|
||||||
static int tcp_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 */
|
send_rpc_query */
|
||||||
|
|
||||||
static void rpc_services_init() {
|
static void rpc_services_init() {
|
||||||
|
static int services_initialized = 0;
|
||||||
|
if (services_initialized) return;
|
||||||
|
services_initialized = 1;
|
||||||
|
|
||||||
char filename[512];
|
char filename[512];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *tmpptr, *p;
|
char *tmpptr, *p;
|
||||||
char line[1024];
|
char line[1024];
|
||||||
int lineno = 0;
|
int lineno = 0;
|
||||||
|
|
||||||
services_initialized = 1;
|
|
||||||
ri.num_alloc = 256;
|
ri.num_alloc = 256;
|
||||||
ri.num_used = 0;
|
ri.num_used = 0;
|
||||||
ri.names = (char **) cp_alloc(ri.num_alloc * sizeof(char *));
|
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) {
|
char *nmap_getrpcnamebynum(unsigned long num) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!services_initialized) {
|
|
||||||
rpc_services_init();
|
rpc_services_init();
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0; i < ri.num_used; i++) {
|
for(i=0; i < ri.num_used; i++) {
|
||||||
if (ri.numbers[i] == num)
|
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) {
|
int get_rpc_procs(unsigned long **programs, unsigned long *num_programs) {
|
||||||
if (!services_initialized) {
|
|
||||||
rpc_services_init();
|
rpc_services_init();
|
||||||
}
|
|
||||||
|
|
||||||
*programs = ri.numbers;
|
*programs = ri.numbers;
|
||||||
*num_programs = ri.num_used;
|
*num_programs = ri.num_used;
|
||||||
@@ -332,7 +330,7 @@ int send_rpc_query(const struct in_addr *target_host, unsigned short portno,
|
|||||||
return 0;
|
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 portinfo *scan, struct scanstats *ss,
|
||||||
struct portinfolist *pil, struct rpcscaninfo *rsi) {
|
struct portinfolist *pil, struct rpcscaninfo *rsi) {
|
||||||
|
|
||||||
|
|||||||
22
osscan.h
22
osscan.h
@@ -120,11 +120,6 @@
|
|||||||
|
|
||||||
/********************** PROTOTYPES ***********************************/
|
/********************** PROTOTYPES ***********************************/
|
||||||
int os_scan(Target *target);
|
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);
|
char *fp2ascii(FingerPrint *FP);
|
||||||
|
|
||||||
/* Parses a single fingerprint from the memory region given. If a
|
/* Parses a single fingerprint from the memory region given. If a
|
||||||
@@ -151,30 +146,13 @@ double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP,
|
|||||||
FingerPrintResults class. */
|
FingerPrintResults class. */
|
||||||
void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
|
void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
|
||||||
FingerPrint **reference_FPs, double accuracy_threshold);
|
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 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);
|
void freeFingerPrint(FingerPrint *FP);
|
||||||
char *mergeFPs(FingerPrint *FPs[], int numFPs, int openport, int closedport,
|
char *mergeFPs(FingerPrint *FPs[], int numFPs, int openport, int closedport,
|
||||||
const u8 *mac);
|
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
|
/* This function takes an array of "numSamples" IP IDs and analyzes
|
||||||
them to determine their sequenceability classification. It returns
|
them to determine their sequenceability classification. It returns
|
||||||
one of the IPID_SEQ_* classifications defined in nmap.h . If the
|
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;
|
static char *logtypes[LOG_NUM_FILES]=LOG_NAMES;
|
||||||
|
|
||||||
/* Used in creating skript kiddie style output. |<-R4d! */
|
/* Used in creating skript kiddie style output. |<-R4d! */
|
||||||
void skid_output(char *s)
|
static void skid_output(char *s)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i=0;s[i];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
|
/* The items in ports should be
|
||||||
in sequential order for space savings and easier to read output. Outputs
|
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) */
|
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 numports) {
|
||||||
int i, previous_port = -2, range_start = -2, port;
|
int i, previous_port = -2, range_start = -2, port;
|
||||||
char outpbuf[128];
|
char outpbuf[128];
|
||||||
@@ -907,6 +907,26 @@ void output_xml_scaninfo_records(struct scan_lists *scanlist) {
|
|||||||
log_flush_all();
|
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
|
/* Helper function to write the status and address/hostname info of a host
|
||||||
into the XML log */
|
into the XML log */
|
||||||
static void write_xml_initial_hostinfo(Target *currenths,
|
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
|
/* 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. */
|
in a certain place to conform to DTD. */
|
||||||
void printmacinfo(Target *currenths);
|
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).
|
/* Write some information (printf style args) to the given log stream(s).
|
||||||
Remember to watch out for format string bugs. */
|
Remember to watch out for format string bugs. */
|
||||||
void log_write(int logt, const char *fmt, ...)
|
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 */
|
it already exists. If the file does not exist, it will be created */
|
||||||
int log_open(int logt, int append, char *filename);
|
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
|
/* Output the list of ports scanned to the top of machine parseable
|
||||||
logs (in a comment, unfortunately). The items in ports should be
|
logs (in a comment, unfortunately). The items in ports should be
|
||||||
in sequential order for space savings and easier to read output */
|
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 tcpscan, int udpscan,
|
||||||
int protscan);
|
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
|
/* Similar to output_ports_to_machine_parseable_output, this function
|
||||||
outputs the XML version, which is scaninfo records of each scan
|
outputs the XML version, which is scaninfo records of each scan
|
||||||
requested and the ports which it will scan for */
|
requested and the ports which it will scan for */
|
||||||
|
|||||||
@@ -103,11 +103,13 @@
|
|||||||
#include "NmapOps.h"
|
#include "NmapOps.h"
|
||||||
|
|
||||||
extern NmapOps o;
|
extern NmapOps o;
|
||||||
static int protocols_initialized = 0;
|
|
||||||
static int numipprots = 0;
|
static int numipprots = 0;
|
||||||
static struct protocol_list *protocol_table[PROTOCOL_TABLE_SIZE];
|
static struct protocol_list *protocol_table[PROTOCOL_TABLE_SIZE];
|
||||||
|
|
||||||
static int nmap_protocols_init() {
|
static int nmap_protocols_init() {
|
||||||
|
static int protocols_initialized = 0;
|
||||||
|
if (protocols_initialized) return 0;
|
||||||
|
|
||||||
char filename[512];
|
char filename[512];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char protocolname[128];
|
char protocolname[128];
|
||||||
@@ -179,7 +181,6 @@ static int nmap_protocols_init() {
|
|||||||
struct protoent *nmap_getprotbynum(int num) {
|
struct protoent *nmap_getprotbynum(int num) {
|
||||||
struct protocol_list *current;
|
struct protocol_list *current;
|
||||||
|
|
||||||
if (!protocols_initialized)
|
|
||||||
if (nmap_protocols_init() == -1)
|
if (nmap_protocols_init() == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -202,7 +203,6 @@ struct scan_lists *getdefaultprots(void) {
|
|||||||
int bucket;
|
int bucket;
|
||||||
int protsneeded = 256;
|
int protsneeded = 256;
|
||||||
|
|
||||||
if (!protocols_initialized)
|
|
||||||
if (nmap_protocols_init() == -1)
|
if (nmap_protocols_init() == -1)
|
||||||
fatal("getdefaultprots(): Couldn't get protocol numbers");
|
fatal("getdefaultprots(): Couldn't get protocol numbers");
|
||||||
|
|
||||||
@@ -224,7 +224,6 @@ struct scan_lists *getfastprots(void) {
|
|||||||
int bucket;
|
int bucket;
|
||||||
int protsneeded = 0;
|
int protsneeded = 0;
|
||||||
|
|
||||||
if (!protocols_initialized)
|
|
||||||
if (nmap_protocols_init() == -1)
|
if (nmap_protocols_init() == -1)
|
||||||
fatal("Getfastprots: Couldn't get protocol numbers");
|
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
|
/* Whether this is storing timing stats for a whole group or an
|
||||||
individual host */
|
individual host */
|
||||||
enum ultra_timing_type { TIMING_HOST, TIMING_GROUP };
|
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,
|
int num_hosts_in_group,
|
||||||
struct ultra_scan_performance_vars *perf,
|
struct ultra_scan_performance_vars *perf,
|
||||||
struct timeval *now);
|
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
|
/* 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
|
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;
|
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
|
/* Adjust various timing variables based on pcket receipt. Pass
|
||||||
rcvdtime = NULL if you have given up on a probe and want to count
|
rcvdtime = NULL if you have given up on a probe and want to count
|
||||||
this as a DROPPED PACKET */
|
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) {
|
UltraProbe *probe, struct timeval *rcvdtime) {
|
||||||
|
|
||||||
int ping_magnifier = (probe->isPing())? USI->perf.ping_magnifier : 1;
|
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. */
|
/* Mark an outstanding probe as timedout. Adjusts stats
|
||||||
static void ultrascan_ping_update(UltraScanInfo *USI, HostScanStats *hss,
|
accordingly. For connect scans, this closes the socket. */
|
||||||
list<UltraProbe *>::iterator probeI,
|
void HostScanStats::markProbeTimedout(list<UltraProbe *>::iterator probeI) {
|
||||||
struct timeval *rcvdtime) {
|
UltraProbe *probe = *probeI;
|
||||||
ultrascan_adjust_times(USI, hss, *probeI, rcvdtime);
|
assert(!probe->timedout);
|
||||||
hss->destroyOutstandingProbe(probeI);
|
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
|
/* Encode the trynum into a 32-bit value. A simple checksum is also included
|
||||||
found to be up or down by a ping/ping_arp scan. The probe that led
|
to verify whether a received version is correct. */
|
||||||
to this new decision is in probeI. This function needs to update
|
static u32 seq32_encode(UltraScanInfo *USI, unsigned int trynum,
|
||||||
timing information and other stats as appropriate.If rcvdtime is
|
unsigned int pingseq) {
|
||||||
NULL, packet stats are not updated. */
|
u32 seq = 0;
|
||||||
static void ultrascan_host_update(UltraScanInfo *USI, HostScanStats *hss,
|
u16 nfo;
|
||||||
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. */
|
/* We'll let pingseq and trynum each be 8 bits */
|
||||||
if ((hss->target->flags & HOST_UP) == 0) {
|
nfo = (pingseq << 8) + trynum;
|
||||||
if (newstate == HOST_UP) {
|
seq = (nfo << 16) + nfo; /* Mirror the data to ensure it is reconstructed correctly */
|
||||||
/* Clear any HOST_DOWN or HOST_FIREWALLED flags */
|
/* Obfuscate it a little */
|
||||||
hss->target->flags &= ~(HOST_DOWN|HOST_FIREWALLED);
|
seq = seq ^ USI->seqmask;
|
||||||
hss->target->flags |= HOST_UP;
|
return seq;
|
||||||
} else if (newstate == HOST_DOWN) {
|
}
|
||||||
hss->target->flags &= ~HOST_FIREWALLED;
|
|
||||||
hss->target->flags |= HOST_DOWN;
|
/* This function provides the proper cwnd and ccthresh to use. It may
|
||||||
} else assert(0);
|
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 */
|
/* Otherwise, use the global cwnd stats if it has sufficient responses */
|
||||||
while(!hss->probes_outstanding.empty())
|
if (USI->gstats->timing.num_updates > 1) {
|
||||||
hss->destroyOutstandingProbe(hss->probes_outstanding.begin());
|
*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
|
/* Like ultrascan_port_probe_update(), except it is called with just a
|
||||||
probespec rather than a whole UltraProbe. Returns true if the port
|
probespec rather than a whole UltraProbe. Returns true if the port
|
||||||
was added or at least the state was changed. */
|
was added or at least the state was changed. */
|
||||||
bool ultrascan_port_pspec_update(UltraScanInfo *USI, HostScanStats *hss,
|
static bool ultrascan_port_pspec_update(UltraScanInfo *USI,
|
||||||
const probespec *pspec, int newstate) {
|
HostScanStats *hss,
|
||||||
|
const probespec *pspec,
|
||||||
|
int newstate) {
|
||||||
u16 portno;
|
u16 portno;
|
||||||
u8 proto = 0;
|
u8 proto = 0;
|
||||||
int oldstate = PORT_TESTING;
|
int oldstate = PORT_TESTING;
|
||||||
@@ -1904,6 +1756,150 @@ bool ultrascan_port_pspec_update(UltraScanInfo *USI, HostScanStats *hss,
|
|||||||
return oldstate != newstate;
|
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.
|
/* 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
|
the port in the probeI of host hss is now in newstate. This
|
||||||
function needs to update timing information, other stats, and the
|
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
|
/* Sends a ping probe to the host. Assumes that caller has already
|
||||||
checked that sending is OK w/congestion control and that pingprobe is
|
checked that sending is OK w/congestion control and that pingprobe is
|
||||||
available */
|
available */
|
||||||
void sendPingProbe(UltraScanInfo *USI, HostScanStats *hss) {
|
static void sendPingProbe(UltraScanInfo *USI, HostScanStats *hss) {
|
||||||
if (o.debugging > 1) {
|
if (o.debugging > 1) {
|
||||||
char tmpbuf[32];
|
char tmpbuf[32];
|
||||||
printf("Ultrascan PING SENT to %s [%s]\n", hss->target->targetipstr(),
|
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
|
/* Print occasional remaining time estimates, as well as
|
||||||
debugging information */
|
debugging information */
|
||||||
void printAnyStats(UltraScanInfo *USI) {
|
static void printAnyStats(UltraScanInfo *USI) {
|
||||||
|
|
||||||
list<HostScanStats *>::iterator hostI;
|
list<HostScanStats *>::iterator hostI;
|
||||||
HostScanStats *hss;
|
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
|
match, or if matching seems to be broken for one reason or
|
||||||
another. You can send in HBO or NBO, just as
|
another. You can send in HBO or NBO, just as
|
||||||
long as the two values are in the same byte order. */
|
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 numvalid = 0;
|
||||||
static int numbogus = 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
|
/* Go through the data structures, making appropriate changes (such as expiring
|
||||||
probes, noting when hosts are complete, etc. */
|
probes, noting when hosts are complete, etc. */
|
||||||
void processData(UltraScanInfo *USI) {
|
static void processData(UltraScanInfo *USI) {
|
||||||
list<HostScanStats *>::iterator hostI;
|
list<HostScanStats *>::iterator hostI;
|
||||||
list<UltraProbe *>::iterator probeI, nextProbeI;
|
list<UltraProbe *>::iterator probeI, nextProbeI;
|
||||||
HostScanStats *host = NULL;
|
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
|
way got overloaded and dropped the last X packets, they are
|
||||||
likely to get through (and flag us a problem if responsive)
|
likely to get through (and flag us a problem if responsive)
|
||||||
if we let them go first in the next round */
|
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;
|
int currentidx, nextidx;
|
||||||
struct portinfo *current;
|
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_write_handler(nsock_pool nsp, nsock_event nse, void *mydata);
|
||||||
void servicescan_connect_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);
|
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() {
|
ServiceProbeMatch::ServiceProbeMatch() {
|
||||||
deflineno = -1;
|
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
|
// 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;
|
ServiceProbe *newProbe;
|
||||||
char line[2048];
|
char line[2048];
|
||||||
int lineno = 0;
|
int lineno = 0;
|
||||||
@@ -1137,6 +1136,17 @@ void parse_nmap_service_probes(AllProbes *AP) {
|
|||||||
parse_nmap_service_probe_file(AP, filename);
|
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
|
// If the buf (of length buflen) matches one of the regexes in this
|
||||||
// ServiceProbe, returns the details of the match (service name,
|
// ServiceProbe, returns the details of the match (service name,
|
||||||
// version number if applicable, and whether this is a "soft" match.
|
// 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;
|
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) {
|
void servicescan_connect_handler(nsock_pool nsp, nsock_event nse, void *mydata) {
|
||||||
nsock_iod nsi = nse_iod(nse);
|
nsock_iod nsi = nse_iod(nse);
|
||||||
enum nse_status status = nse_status(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
|
// This is used in processResults to determine whether a FP
|
||||||
// should be printed based on type of match, version intensity, etc.
|
// should be printed based on type of match, version intensity, etc.
|
||||||
|
static int shouldWePrintFingerprint(ServiceNFO *svc) {
|
||||||
int shouldWePrintFingerprint(ServiceNFO *svc) {
|
|
||||||
// Never print FP if hardmatched
|
// Never print FP if hardmatched
|
||||||
if (svc->probe_state == PROBESTATE_FINISHED_HARDMATCHED)
|
if (svc->probe_state == PROBESTATE_FINISHED_HARDMATCHED)
|
||||||
return 0;
|
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
|
/* Start the timeout clocks of any targets that have probes. Assumes
|
||||||
that this is called before any probes have been launched (so they
|
that this is called before any probes have been launched (so they
|
||||||
are all in services_remaining */
|
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
|
// We iterate through SG->services_remaining and remove any with port/protocol
|
||||||
// pairs that are excluded. We use AP->isExcluded() to determine which ports
|
// pairs that are excluded. We use AP->isExcluded() to determine which ports
|
||||||
// are excluded.
|
// are excluded.
|
||||||
void remove_excluded_ports(AllProbes *AP, ServiceGroup *SG) {
|
static void remove_excluded_ports(AllProbes *AP, ServiceGroup *SG) {
|
||||||
list<ServiceNFO *>::iterator i, nxt;
|
list<ServiceNFO *>::iterator i, nxt;
|
||||||
ServiceNFO *svc;
|
ServiceNFO *svc;
|
||||||
|
|
||||||
@@ -2311,7 +2320,7 @@ void remove_excluded_ports(AllProbes *AP, ServiceGroup *SG) {
|
|||||||
Targets specified. */
|
Targets specified. */
|
||||||
int service_scan(vector<Target *> &Targets) {
|
int service_scan(vector<Target *> &Targets) {
|
||||||
// int service_scan(Target *targets[], int num_targets)
|
// int service_scan(Target *targets[], int num_targets)
|
||||||
static AllProbes *AP;
|
AllProbes *AP;
|
||||||
ServiceGroup *SG;
|
ServiceGroup *SG;
|
||||||
nsock_pool nsp;
|
nsock_pool nsp;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
@@ -2323,10 +2332,7 @@ int service_scan(vector<Target *> &Targets) {
|
|||||||
if (Targets.size() == 0)
|
if (Targets.size() == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!AP) {
|
AP = service_scan_init();
|
||||||
AP = new AllProbes();
|
|
||||||
parse_nmap_service_probes(AP);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Now I convert the targets into a new ServiceGroup
|
// Now I convert the targets into a new ServiceGroup
|
||||||
|
|||||||
@@ -341,8 +341,5 @@ public:
|
|||||||
Targets specified. */
|
Targets specified. */
|
||||||
int service_scan(std::vector<Target *> &Targets);
|
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 */
|
#endif /* SERVICE_SCAN_H */
|
||||||
|
|
||||||
|
|||||||
@@ -103,12 +103,14 @@
|
|||||||
#include "NmapOps.h"
|
#include "NmapOps.h"
|
||||||
|
|
||||||
extern NmapOps o;
|
extern NmapOps o;
|
||||||
static int services_initialized = 0;
|
|
||||||
static int numtcpports = 0;
|
static int numtcpports = 0;
|
||||||
static int numudpports = 0;
|
static int numudpports = 0;
|
||||||
static struct service_list *service_table[SERVICE_TABLE_SIZE];
|
static struct service_list *service_table[SERVICE_TABLE_SIZE];
|
||||||
|
|
||||||
static int nmap_services_init() {
|
static int nmap_services_init() {
|
||||||
|
static int services_initialized = 0;
|
||||||
|
if (services_initialized) return 0;
|
||||||
|
|
||||||
char filename[512];
|
char filename[512];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char servicename[128], proto[16];
|
char servicename[128], proto[16];
|
||||||
@@ -216,7 +218,6 @@ static int nmap_services_init() {
|
|||||||
struct servent *nmap_getservbyport(int port, const char *proto) {
|
struct servent *nmap_getservbyport(int port, const char *proto) {
|
||||||
struct service_list *current;
|
struct service_list *current;
|
||||||
|
|
||||||
if (!services_initialized)
|
|
||||||
if (nmap_services_init() == -1)
|
if (nmap_services_init() == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -244,7 +245,6 @@ struct scan_lists *getdefaultports(int tcpscan, int udpscan) {
|
|||||||
int tcpportsneeded = 0;
|
int tcpportsneeded = 0;
|
||||||
int udpportsneeded = 0;
|
int udpportsneeded = 0;
|
||||||
|
|
||||||
if (!services_initialized)
|
|
||||||
if (nmap_services_init() == -1)
|
if (nmap_services_init() == -1)
|
||||||
fatal("Getfastports: Couldn't get port numbers");
|
fatal("Getfastports: Couldn't get port numbers");
|
||||||
|
|
||||||
@@ -308,7 +308,6 @@ struct scan_lists *getfastports(int tcpscan, int udpscan) {
|
|||||||
int tcpportsneeded = 0;
|
int tcpportsneeded = 0;
|
||||||
int udpportsneeded = 0;
|
int udpportsneeded = 0;
|
||||||
|
|
||||||
if (!services_initialized)
|
|
||||||
if (nmap_services_init() == -1)
|
if (nmap_services_init() == -1)
|
||||||
fatal("Getfastports: Couldn't get port numbers");
|
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),
|
/* 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) */
|
you can just pass NULL (it is only a stupid optimization that needs it) */
|
||||||
Target *nexthost(HostGroupState *hs, TargetGroup *exclude_group,
|
Target *nexthost(HostGroupState *hs, TargetGroup *exclude_group,
|
||||||
struct scan_lists *ports, int *pingtype);
|
struct scan_lists *ports, int *pingtype);
|
||||||
/* loads an exclude file into a excluded target list */
|
/* loads an exclude file into a excluded target list */
|
||||||
TargetGroup* load_exclude(FILE *fExclude, char *szExclude);
|
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. */
|
/* a debugging routine to dump an exclude list to stdout. */
|
||||||
int dumpExclude(TargetGroup*exclude_group);
|
int dumpExclude(TargetGroup*exclude_group);
|
||||||
/* Returns the last host obtained by nexthost. It will be given again the next
|
/* 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;
|
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
|
/* 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
|
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".
|
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
|
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
|
within (say) printf(). And certainly don't try to free() it! The
|
||||||
returned buffer is NUL-terminated */
|
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];
|
static char protoinfo[256];
|
||||||
struct ip *ip = (struct ip *) packet;
|
struct ip *ip = (struct ip *) packet;
|
||||||
struct tcphdr *tcp;
|
struct tcphdr *tcp;
|
||||||
@@ -619,6 +476,148 @@ const char *ippackethdrinfo(const u8 *packet, u32 len) {
|
|||||||
return protoinfo;
|
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) {
|
int islocalhost(const struct in_addr * const addr) {
|
||||||
char dev[128];
|
char dev[128];
|
||||||
@@ -937,6 +936,87 @@ int send_tcp_raw( int sd, struct eth_nfo *eth, const struct in_addr *source,
|
|||||||
return res;
|
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 */
|
/* Send a pre-built IPv4 packet */
|
||||||
int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetlen) {
|
int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetlen) {
|
||||||
struct sockaddr_in sock;
|
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;
|
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
|
/* Builds an ICMP packet (including an IP header) by packing the fields
|
||||||
with the given information. It allocates a new buffer to store the
|
with the given information. It allocates a new buffer to store the
|
||||||
packet contents, and then returns that buffer. The packet is not
|
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);
|
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
|
/* A simple function I wrote to help in debugging, shows the important fields
|
||||||
of a TCP packet*/
|
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
|
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
|
IP ss will be overwritten with the new MAC address. true is always
|
||||||
returned for the set command. */
|
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 sockaddr_in *sin = (struct sockaddr_in *) ss;
|
||||||
struct ArpCache {
|
struct ArpCache {
|
||||||
u32 ip; /* Network byte order */
|
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
|
broadcast MAC address. The transmission is attempted up to 3
|
||||||
times. If none of these elicit a response, false will be returned.
|
times. If none of these elicit a response, false will be returned.
|
||||||
If the mac is determined, true is 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 *srcip,
|
||||||
const struct sockaddr_storage *targetip, u8 *targetmac) {
|
const struct sockaddr_storage *targetip, u8 *targetmac) {
|
||||||
/* timeouts in microseconds ... the first ones are retransmit times, while
|
/* timeouts in microseconds ... the first ones are retransmit times, while
|
||||||
@@ -2084,7 +2106,7 @@ struct dnet_collector_route_nfo {
|
|||||||
int numifaces;
|
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;
|
struct dnet_collector_route_nfo *dcrn = (struct dnet_collector_route_nfo *) arg;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -2122,7 +2144,7 @@ int collect_dnet_routes(const struct route_entry *entry, void *arg) {
|
|||||||
return 0;
|
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;
|
struct dnet_collector_route_nfo *dcrn = (struct dnet_collector_route_nfo *) arg;
|
||||||
int i;
|
int i;
|
||||||
int numifaces = dcrn->numifaces;
|
int numifaces = dcrn->numifaces;
|
||||||
@@ -2840,41 +2862,6 @@ if (echots) *echots = 0;
|
|||||||
return 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() {
|
IPProbe::IPProbe() {
|
||||||
packetbuflen = 0;
|
packetbuflen = 0;
|
||||||
packetbuf = NULL;
|
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,
|
int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet,
|
||||||
unsigned int packetlen);
|
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 ... */
|
/* Decoy versions of the raw packet sending functions ... */
|
||||||
int send_tcp_raw_decoys( int sd, struct eth_nfo *eth,
|
int send_tcp_raw_decoys( int sd, struct eth_nfo *eth,
|
||||||
const struct in_addr *victim, int ttl,
|
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.
|
// invalid (Windows and Amiga), readip_pcap returns the time you called it.
|
||||||
bool pcap_recv_timeval_valid();
|
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
|
/* A simple function I wrote to help in debugging, shows the important fields
|
||||||
of a TCP packet*/
|
of a TCP packet*/
|
||||||
int readtcppacket(const u8 *packet, int readdata);
|
int readtcppacket(const u8 *packet, int readdata);
|
||||||
@@ -726,8 +712,6 @@ bool setTargetNextHopMAC(Target *target);
|
|||||||
|
|
||||||
int islocalhost(const struct in_addr * const addr);
|
int islocalhost(const struct in_addr * const addr);
|
||||||
int unblock_socket(int sd);
|
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
|
// Takes a protocol number like IPPROTO_TCP, IPPROTO_UDP, or
|
||||||
// IPPROTO_TCP and returns a ascii representation (or "unknown" if it
|
// 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,
|
char *readip_pcap(pcap_t *pd, unsigned int *len, long to_usec,
|
||||||
struct timeval *rcvdtime, struct link_header *linknfo);
|
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
|
/* Attempts to read one IPv4/Ethernet ARP reply packet from the pcap
|
||||||
descriptor pd. If it receives one, fills in sendermac (must pass
|
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)
|
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,
|
int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac, struct in_addr *senderIP,
|
||||||
long to_usec, struct timeval *rcvdtime);
|
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
|
#ifndef HAVE_INET_ATON
|
||||||
int inet_aton(register const char *, struct in_addr *);
|
int inet_aton(register const char *, struct in_addr *);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
66
tty.cc
66
tty.cc
@@ -127,7 +127,7 @@ extern NmapOps o;
|
|||||||
// Microsoft's runtime makes this fairly simple. :)
|
// Microsoft's runtime makes this fairly simple. :)
|
||||||
void tty_init() { return; }
|
void tty_init() { return; }
|
||||||
static int tty_getchar() { return _kbhit() ? getch() : -1; }
|
static int tty_getchar() { return _kbhit() ? getch() : -1; }
|
||||||
void tty_done() { return; }
|
static void tty_done() { return; }
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#if !defined(O_NONBLOCK) && defined(O_NDELAY)
|
#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 int tty_fd = 0;
|
||||||
static struct termios saved_ti;
|
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()
|
static int tty_getchar()
|
||||||
{
|
{
|
||||||
int c, numChars;
|
int c, numChars;
|
||||||
@@ -200,7 +173,7 @@ static int tty_getchar()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tty_done()
|
static void tty_done()
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -212,14 +185,45 @@ void tty_done()
|
|||||||
close(fd);
|
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
|
#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
|
keypresses and interpret them, and it will also tell you if you
|
||||||
should print anything. A value of true being returned means a
|
should print anything. A value of true being returned means a
|
||||||
nonstandard key has been pressed and the calling method should
|
nonstandard key has been pressed and the calling method should
|
||||||
print a status message */
|
print a status message */
|
||||||
|
|
||||||
bool keyWasPressed()
|
bool keyWasPressed()
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|||||||
16
tty.h
16
tty.h
@@ -97,15 +97,15 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes the terminal for unbuffered non-blocking input. Also registers
|
* Initializes the terminal for unbuffered non-blocking input. Also
|
||||||
* tty_done() via atexit().
|
* registers tty_done() via atexit(). You need to call this before
|
||||||
|
* you ever call keyWasPressed().
|
||||||
*/
|
*/
|
||||||
void tty_init();
|
void tty_init();
|
||||||
|
|
||||||
/*
|
/* Catches all of the predefined keypresses and interpret them, and it
|
||||||
* Restores the terminal parameters and closes the file descriptor.
|
will also tell you if you should print anything. A value of true
|
||||||
*/
|
being returned means a nonstandard key has been pressed and the
|
||||||
void tty_done();
|
calling method should print a status message */
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
bool keyWasPressed();
|
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;
|
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 gcd_n_uint(int nvals, unsigned int *val)
|
||||||
{
|
{
|
||||||
unsigned int a,b,c;
|
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.
|
// 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);
|
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);
|
unsigned int gcd_n_uint(int nvals, unsigned int *val);
|
||||||
|
|
||||||
int arg_parse(const char *command, char ***argv);
|
int arg_parse(const char *command, char ***argv);
|
||||||
|
|||||||
Reference in New Issue
Block a user