diff -urNb old.nmap-4.60/Makefile.in new.nmap-4.60/Makefile.in
--- old.nmap-4.60/Makefile.in 2008-01-23 19:36:01.000000000 -0600
+++ new.nmap-4.60/Makefile.in 2008-03-17 11:09:03.059920000 -0500
@@ -65,11 +65,11 @@
NSESTDLIB=nsestdlib
endif
-export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc osscan2.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc nmap_tty.cc nmap_dns.cc traceroute.cc portreasons.cc $(NSE_SRC) @COMPAT_SRCS@
+export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc osscan2.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc nmap_tty.cc nmap_dns.cc traceroute.cc portreasons.cc qscan.cc $(NSE_SRC) @COMPAT_SRCS@
export HDRS = charpool.h FingerPrintResults.h global_structures.h idle_scan.h MACLookup.h nmap_amigaos.h nmap_dns.h nmap_error.h nmap.h NmapOps.h NmapOutputTable.h nmap_rpc.h nmap_tty.h nmap_winconfig.h osscan.h osscan2.h output.h portlist.h protocols.h scan_engine.h service_scan.h services.h TargetGroup.h Target.h targets.h tcpip.h timing.h utils.h traceroute.h portreasons.h $(NSE_HDRS)
-OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o osscan2.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o nmap_tty.o nmap_dns.o traceroute.o portreasons.o $(NSE_OBJS) @COMPAT_OBJS@
+OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o osscan2.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o nmap_tty.o nmap_dns.o traceroute.o portreasons.o qscan.o $(NSE_OBJS) @COMPAT_OBJS@
# %.o : %.cc -- nope this is a GNU extension
.cc.o:
diff -urNb old.nmap-4.60/NmapOps.cc new.nmap-4.60/NmapOps.cc
--- old.nmap-4.60/NmapOps.cc 2008-02-28 12:52:06.000000000 -0600
+++ new.nmap-4.60/NmapOps.cc 2008-03-17 11:17:52.054451500 -0500
@@ -238,7 +238,7 @@
version_intensity = 7;
pingtype = PINGTYPE_UNKNOWN;
listscan = pingscan = allowall = ackscan = bouncescan = connectscan = 0;
- rpcscan = nullscan = xmasscan = fragscan = synscan = windowscan = 0;
+ rpcscan = nullscan = xmasscan = fragscan = synscan = windowscan = qscan = 0;
maimonscan = idlescan = finscan = udpscan = ipprotscan = noresolve = 0;
append_output = 0;
memset(logfd, 0, sizeof(FILE *) * LOG_NUM_FILES);
@@ -270,6 +270,9 @@
ipopt_lasthop = 0;
release_memory = false;
topportlevel = -1;
+ qscan_delay = 200;
+ qscan_numtrips = 10;
+ qscan_confidence = 0.95;
#ifndef NOLUA
script = 0;
scriptversion = 0;
@@ -279,7 +282,7 @@
}
bool NmapOps::TCPScan() {
- return ackscan|bouncescan|connectscan|finscan|idlescan|maimonscan|nullscan|synscan|windowscan|xmasscan;
+ return ackscan|bouncescan|connectscan|finscan|idlescan|maimonscan|nullscan|synscan|windowscan|xmasscan|qscan;
}
bool NmapOps::UDPScan() {
@@ -291,7 +294,7 @@
IPv6 is being used. It will return false in those cases where a
RawScan is not neccessarily used. */
bool NmapOps::RawScan() {
- if (ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|osscan|synscan|udpscan|windowscan|xmasscan)
+ if (ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|osscan|synscan|udpscan|windowscan|xmasscan|qscan)
return true;
if (pingtype & (PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS|PINGTYPE_TCP_USE_ACK|PINGTYPE_UDP))
return true;
diff -urNb old.nmap-4.60/NmapOps.h new.nmap-4.60/NmapOps.h
--- old.nmap-4.60/NmapOps.h 2008-02-28 12:52:06.000000000 -0600
+++ new.nmap-4.60/NmapOps.h 2008-03-17 11:19:36.822088000 -0500
@@ -296,6 +296,7 @@
int ipprotscan;
int maimonscan;
int nullscan;
+ int qscan;
int rpcscan;
int synscan;
int udpscan;
@@ -322,6 +323,9 @@
bool log_errors;
bool traceroute;
bool reason;
+ int qscan_delay;
+ int qscan_numtrips;
+ double qscan_confidence;
#ifndef NOLUA
int script;
Files old.nmap-4.60/mswin32/nmap.ncb and new.nmap-4.60/mswin32/nmap.ncb differ
Files old.nmap-4.60/mswin32/nmap.suo and new.nmap-4.60/mswin32/nmap.suo differ
diff -urNb old.nmap-4.60/mswin32/nmap.vcproj new.nmap-4.60/mswin32/nmap.vcproj
--- old.nmap-4.60/mswin32/nmap.vcproj 2007-11-27 17:48:33.000000000 -0600
+++ new.nmap-4.60/mswin32/nmap.vcproj 2008-03-17 11:22:29.825409600 -0500
@@ -318,6 +318,10 @@
>
+
+
diff -urNb old.nmap-4.60/nmap.cc new.nmap-4.60/nmap.cc
--- old.nmap-4.60/nmap.cc 2008-02-28 12:52:06.000000000 -0600
+++ new.nmap-4.60/nmap.cc 2008-03-17 11:13:57.456197300 -0500
@@ -241,6 +241,9 @@
" -b : FTP bounce scan\n"
" --traceroute: Trace hop path to each host\n"
" --reason: Display the reason a port is in a particular state\n"
+ " --qscan-delay : Average delay between qscan packets\n"
+ " --qscan-numtrip : Round trip times to record\n"
+ " --qscan-confidence : Confidence level (default 0.95)\n"
"PORT SPECIFICATION AND SCAN ORDER:\n"
" -p : Only scan specified ports\n"
" Ex: -p22; -p1-65535; -p U:53,111,137,T:21-25,80,139,8080\n"
@@ -623,6 +626,9 @@
{"port_ratio", required_argument, 0, 0},
{"top-ports", required_argument, 0, 0},
{"top_ports", required_argument, 0, 0},
+ {"qscan-delay", required_argument, 0, 0},
+ {"qscan-numtrips", required_argument, 0, 0},
+ {"qscan-confidence", required_argument, 0, 0},
#ifndef NOLUA
{"script", required_argument, 0, 0},
{"script-trace", no_argument, 0, 0},
@@ -817,6 +823,18 @@
o.mass_dns = false;
} else if (optcmp(long_options[option_index].name, "dns-servers") == 0) {
o.dns_servers = strdup(optarg);
+ } else if (optcmp(long_options[option_index].name, "qscan-delay") == 0) {
+ o.qscan_delay = atoi(optarg);
+ if (o.qscan_delay <= 0)
+ fatal("qscan-delay must be greater than 0");
+ } else if (optcmp(long_options[option_index].name, "qscan-numtrips") == 0) {
+ o.qscan_numtrips = atoi(optarg);
+ if (o.qscan_numtrips < 3)
+ fatal("qscan-numtrips must be 3 or greater");
+ } else if (optcmp(long_options[option_index].name, "qscan-confidence") == 0) {
+ o.qscan_confidence = atof(optarg);
+ if (o.qscan_confidence <= 0 || o.qscan_confidence >= 1.0)
+ fatal("qscan-confidence must be between 0 and 1");
} else if (optcmp(long_options[option_index].name, "log-errors") == 0) {
o.log_errors = 1;
} else if (strcmp(long_options[option_index].name, "webxml") == 0) {
@@ -1134,6 +1152,7 @@
case 'N': o.nullscan = 1; break;
case 'O': o.ipprotscan = 1; break;
case 'P': o.pingscan = 1; break;
+ case 'Q': o.qscan = 1; randomize = 0; break;
case 'R': o.rpcscan = 1; break;
case 'S': o.synscan = 1; break;
case 'W': o.windowscan = 1; break;
@@ -1703,6 +1722,9 @@
if (o.ipprotscan)
ultra_scan(Targets, ports, IPPROT_SCAN);
+ if (o.qscan)
+ qscan(&Targets[0], Targets.size(), ports);
+
/* These lame functions can only handle one target at a time */
for(targetno = 0; targetno < Targets.size(); targetno++) {
currenths = Targets[targetno];
diff -urNb old.nmap-4.60/nmap.h new.nmap-4.60/nmap.h
--- old.nmap-4.60/nmap.h 2008-03-14 20:21:22.000000000 -0500
+++ new.nmap-4.60/nmap.h 2008-03-17 11:15:08.160679800 -0500
@@ -443,4 +443,6 @@
int nmap_fileexistsandisreadable(char* pathname);
int gather_logfile_resumption_state(char *fname, int *myargc, char ***myargv);
+void qscan(Target **targets, int num_targets, struct scan_lists *ports);
+
#endif /* NMAP_H */
diff -urNb old.nmap-4.60/output.cc new.nmap-4.60/output.cc
--- old.nmap-4.60/output.cc 2008-02-28 12:52:06.000000000 -0600
+++ new.nmap-4.60/output.cc 2008-03-17 11:20:52.620418300 -0500
@@ -453,6 +453,9 @@
vector saved_servicefps;
+ // QScan doesn't print port status information at all!
+ if (o.qscan) return;
+
log_write(LOG_XML, "");
int prevstate = PORT_UNKNOWN;
int istate;
diff -urNb old.nmap-4.60/qscan.cc new.nmap-4.60/qscan.cc
--- old.nmap-4.60/qscan.cc 1969-12-31 18:00:00.000000000 -0600
+++ new.nmap-4.60/qscan.cc 2008-03-17 11:34:36.339358400 -0500
@@ -0,0 +1,391 @@
+#include
+#include
+#include
+#include
+#if HAVE_SYS_TIME_H
+#include
+#endif
+
+#include "nmap.h"
+#include "Target.h"
+#include "NmapOps.h"
+#include "nmap_tty.h"
+#include "utils.h"
+#include "timing.h"
+
+
+// Outstanding probe window
+#define OWIN_SIZE 6
+#define TIMEOUT_NUM 10
+
+struct qtarg_s {
+ Target *t;
+ int port;
+
+ struct timeval owin[OWIN_SIZE];
+ int owin_offset;
+ int recvs, trans;
+
+ int num;
+ double mean, s_knuth; // Variance = s_knuth/(n-1)
+
+ int family;
+
+ struct qtarg_s *next;
+};
+
+static int rawsd, tcpPortBase;
+static pcap_t *pd;
+static struct eth_nfo eth;
+static struct eth_nfo *ethptr;
+static struct qtarg_s *qtargbase;
+static ScanProgressMeter *SPM;
+static int total_n=0, total_n_needed;
+
+
+extern NmapOps o;
+
+
+// Calculates the intermediate statistic 't given
+// the quantity, mean, and standard deviation of 2 samples.
+double calculate_t(int n1, int n2, double u1, double u2, double s1, double s2) {
+ double a, b;
+ double dof = n1 + n2 - 2;
+
+ a = ((double)n1 + n2) / (n1 * n2);
+ b = ((n1-1) * (s1*s1)) + ((n2-1) * (s2*s2));
+ b /= dof;
+
+ return fabs(u1 - u2) / sqrt(a*b);
+
+}
+
+/* http://www.owlnet.rice.edu/~elec428/projects/tinv.c
+ * Uncredited ?
+ * tinv(p,dof) returns the inverse t-distribution value for probability
+ * 'p and degrees of freedom 'dof. It does this by looking up the appropriate
+ * value in the array tinv_array. Only dof between 1 and 20 are exact.
+ * For dof > 20, tinv() returns approximations. Also, only probabilities
+ * of 0.75, 0.9, 0.95, 0.975, 0.99, 0.995, and 0.9995 are provided.
+ *
+ * If p is not one of the 7 provided values, or if dof is not greater than or
+ * equal to 1, tinv() causes the program to exit.
+ */
+
+double tinv(double p, int dof) {
+ int dofindex,pindex;
+
+ double tinv_array[31][7] = {
+ {1.0000, 3.0777, 6.3138, 12.7062, 31.8207, 63.6574, 636.6192}, /* 1 */
+ {0.8165, 1.8856, 2.9200, 4.3027, 6.9646, 9.9248, 31.5991}, /* 2 */
+ {0.7649, 1.6377, 2.3534, 3.1824, 4.5407, 5.8409, 12.9240}, /* 3 */
+ {0.7407, 1.5332, 2.1318, 2.7764, 3.7649, 4.6041, 8.6103}, /* 4 */
+ {0.7267, 1.4759, 2.0150, 2.5706, 3.3649, 4.0322, 6.8688}, /* 5 */
+ {0.7176, 1.4398, 1.9432, 2.4469, 3.1427, 3.7074, 5.9588}, /* 6 */
+ {0.7111, 1.4149, 1.8946, 2.3646, 2.9980, 3.4995, 5.4079}, /* 7 */
+ {0.7064, 1.3968, 1.8595, 3.3060, 2.8965, 3.3554, 5.0413}, /* 8 */
+ {0.7027, 1.3830, 1.8331, 2.2622, 2.8214, 3.2498, 4.7809}, /* 9 */
+ {0.6998, 1.3722, 1.8125, 2.2281, 2.7638, 1.1693, 4.5869}, /* 10 */
+ {0.6974, 1.3634, 1.7959, 2.2010, 2.7181, 3.1058, 4.4370}, /* 11 */
+ {0.6955, 1.3562, 1.7823, 2.1788, 2.6810, 3.0545, 4.3178}, /* 12 */
+ {0.6938, 1.3502, 1.7709, 2.1604, 2.6403, 3.0123, 4.2208}, /* 13 */
+ {0.6924, 1.3450, 1.7613, 2.1448, 2.6245, 2.9768, 4.1405}, /* 14 */
+ {0.6912, 1.3406, 1.7531, 2.1315, 2.6025, 2.9467, 4.0728}, /* 15 */
+ {0.6901, 1.3368, 1.7459, 2.1199, 2.5835, 2.9208, 4.0150}, /* 16 */
+ {0.6892, 1.3334, 1.7396, 2.1098, 2.5669, 2.8982, 3.9651}, /* 17 */
+ {0.6884, 1.3304, 1.7341, 2.1009, 2.5524, 2.8784, 3.9216}, /* 18 */
+ {0.6876, 1.3277, 1.7291, 2.0930, 2.5395, 2.8609, 3.8834}, /* 19 */
+ {0.6870, 1.3253, 1.7247, 2.0860, 2.5280, 2.8453, 3.8495}, /* 20 */
+ {0.6844, 1.3163, 1.7081, 2.0595, 2.4851, 2.7874, 3.7251}, /* 25 */
+ {0.6828, 1.3104, 1.6973, 2.0423, 2.4573, 2.7500, 3.6460}, /* 30 */
+ {0.6816, 1.3062, 1.6896, 2.0301, 2.4377, 2.7238, 3.5911}, /* 35 */
+ {0.6807, 1.3031, 1.6839, 2.0211, 2.4233, 2.7045, 3.5510}, /* 40 */
+ {0.6800, 1.3006, 1.6794, 2.0141, 2.4121, 2.6896, 3.5203}, /* 45 */
+ {0.6794, 1.2987, 1.6759, 2.0086, 2.4033, 2.6778, 3.4960}, /* 50 */
+ {0.6786, 1.2958, 1.6706, 2.0003, 2.3901, 2.6603, 3.4602}, /* 60 */
+ {0.6780, 1.2938, 1.6669, 1.9944, 2.3808, 2.6479, 3.4350}, /* 70 */
+ {0.6776, 1.2922, 1.6641, 1.9901, 2.3739, 2.6387, 3.4163}, /* 80 */
+ {0.6772, 1.2910, 1.6620, 1.9867, 2.3685, 2.6316, 3.4019}, /* 90 */
+ {0.6770, 1.2901, 1.6602, 1.9840, 2.3642, 2.6259, 3.3905}}; /* 100 */
+
+ if (dof >= 1 && dof <= 20) dofindex = dof-1;
+ else if (dof < 25) dofindex = 19;
+ else if (dof < 30) dofindex = 20;
+ else if (dof < 35) dofindex = 21;
+ else if (dof < 40) dofindex = 22;
+ else if (dof < 45) dofindex = 23;
+ else if (dof < 50) dofindex = 24;
+ else if (dof < 60) dofindex = 25;
+ else if (dof < 70) dofindex = 26;
+ else if (dof < 80) dofindex = 27;
+ else if (dof < 90) dofindex = 28;
+ else if (dof < 100) dofindex = 29;
+ else if (dof >= 100) dofindex = 30;
+ else
+ {
+ printf("tinv: degrees of freedom must be at least 1\n");
+ exit(1);
+ }
+
+ if (p == .75) pindex = 0;
+ else if (p == .9) pindex = 1;
+ else if (p == .95) pindex = 2;
+ else if (p == .975) pindex = 3;
+ else if (p == .99) pindex = 4;
+ else if (p == .995) pindex = 5;
+ else if (p == .9995) pindex = 6;
+ else
+ {
+ printf("tinv: probability not tabulated\n");
+ exit(1);
+ }
+
+ return(tinv_array[dofindex][pindex]);
+}
+
+
+
+void qscan_transmit(struct qtarg_s *qt, struct timeval *now) {
+ send_tcp_raw(rawsd, ethptr, qt->t->v4sourceip(), qt->t->v4hostip(), o.ttl, false, NULL, 0,
+ tcpPortBase + qt->owin_offset, qt->port, get_random_u32(), get_random_u32(), 0, TH_SYN,
+ 0, 0, NULL, 0, NULL, 0);
+
+ qt->owin[qt->owin_offset].tv_sec = now->tv_sec;
+ qt->owin[qt->owin_offset].tv_usec = now->tv_usec;
+
+ qt->owin_offset = (qt->owin_offset+1) % OWIN_SIZE;
+
+ qt->trans++;
+}
+
+
+// Numerically stable running tally of n, mean, and variance.
+// Algorithm from:
+// Donald E. Knuth (1998). The Art of Computer Programming, volume 2:
+// Seminumerical Algorithms, 3rd edn., p. 232. Boston: Addison-Wesley.
+void update_statistics(struct qtarg_s *qt, double rtt_ms) {
+ double delta;
+
+ total_n++;
+ qt->num++;
+ delta = rtt_ms - qt->mean;
+ qt->mean += delta/qt->num;
+ qt->s_knuth += delta * (rtt_ms - qt->mean);
+}
+
+
+void qscan_families() {
+ struct qtarg_s *qti, *qtj;
+ double t, critical_value;
+ int curr_family = 0;
+
+ for (qti=qtargbase; qti; qti=qti->next) {
+ if (qti->family != -1) continue;
+
+ qti->family = curr_family++;
+
+ for (qtj=qti->next; qtj; qtj=qtj->next) {
+ if (qtj->family != -1) continue;
+
+ t = calculate_t(qti->num, qtj->num,
+ qti->mean, qtj->mean,
+ sqrt(qti->s_knuth/(qti->num-1)), sqrt(qtj->s_knuth/(qtj->num-1)));
+
+ critical_value = tinv(o.qscan_confidence, qti->num + qtj->num - 2);
+
+ if (t < critical_value) qtj->family = qti->family;
+ }
+ }
+
+}
+
+
+void qscan_parse_packet(struct ip *myip, struct timeval *seen) {
+ struct tcp_hdr *tcp;
+ int sport, dport;
+ struct in_addr saddr;
+ struct qtarg_s *qt;
+ double rtt_ms;
+
+ saddr = myip->ip_src;
+ tcp = (struct tcp_hdr *) ((u8 *) myip + myip->ip_hl * 4);
+ sport = ntohs(tcp->th_sport);
+ dport = ntohs(tcp->th_dport);
+
+ // We're only after resets or syn|acks..
+ if ((tcp->th_flags & TH_RST) == 0 && tcp->th_flags != (TH_SYN|TH_ACK)) return;
+
+ if (dport < tcpPortBase || dport >= (tcpPortBase + OWIN_SIZE)) return;
+
+ for (qt=qtargbase; qt!=NULL; qt=qt->next)
+ if (memcmp(qt->t->v4hostip(), &saddr, sizeof(struct in_addr)) == 0
+ && sport == qt->port) break;
+
+ if (qt == NULL) return;
+
+ // Something fisy going on if this returns: An unexpected reply...
+ // We'll just ignore for now.
+ if (qt->owin[dport - tcpPortBase].tv_sec == -1) return;
+
+ rtt_ms = TIMEVAL_SUBTRACT(*seen, qt->owin[dport - tcpPortBase]) / 1000.0;
+
+ if (qt->recvs++ > OWIN_SIZE)
+ update_statistics(qt, rtt_ms);
+
+ qt->owin[dport - tcpPortBase].tv_sec = -1;
+}
+
+
+void qscan_run() {
+ struct qtarg_s *qt = qtargbase, *qtp;
+ struct timeval tv, now, seen;
+ struct ip *myip;
+ unsigned int len;
+ int minpackets;
+ int finished=0;
+
+ while(1) {
+ gettimeofday(&now, NULL);
+ qscan_transmit(qt, &now);
+
+ qt = qt->next;
+ if (qt == NULL) qt = qtargbase;
+
+ // Random wait from N/2 to 3N/2 ms between transmissions
+ TIMEVAL_MSEC_ADD(tv, now, (get_random_u16() % o.qscan_delay) + (o.qscan_delay / 2));
+
+ do {
+ if (keyWasPressed())
+ SPM->printStats((double) total_n / total_n_needed, NULL);
+
+ myip = (struct ip *) readip_pcap(pd, &len, TIMEVAL_SUBTRACT(tv, now), &seen, NULL);
+
+ if (myip != NULL)
+ qscan_parse_packet(myip, &seen);
+
+ for (qtp=qtargbase, minpackets=o.qscan_numtrips; qtp!=NULL; qtp=qtp->next)
+ if ((qtp->trans-TIMEOUT_NUM) < qtp->recvs && qtp->num < minpackets) minpackets = qtp->num;
+
+ if (!finished && minpackets == o.qscan_numtrips) {
+ finished=1;
+ gettimeofday(&now, NULL);
+ TIMEVAL_MSEC_ADD(tv, now, (o.qscan_delay*3)/2);
+ }
+
+ gettimeofday(&now, NULL);
+ } while(TIMEVAL_SUBTRACT(tv, now) > 0);
+
+ if (finished) return;
+ }
+}
+
+
+
+void qscan(Target **targets, int num_targets, struct scan_lists *ports) {
+ int i, j, k;
+ struct qtarg_s *qt, *qt2;
+ char pcap_filter[2048];
+
+ if (num_targets == 0 || ports->tcp_count == 0)
+ fatal("Qscan: No targets or no TCP ports specified");
+
+ rawsd = -1;
+ qtargbase = NULL;
+ tcpPortBase = o.magic_port_set? o.magic_port : o.magic_port + get_random_u8();
+ total_n_needed = num_targets * ports->tcp_count * o.qscan_numtrips;
+
+ // Initialise our main linked list
+ for (i=0; itcp_count-1; j>=0; j--) {
+ qt = (struct qtarg_s *) malloc(sizeof(struct qtarg_s));
+ if (qt == NULL) fatal("Qscan: out of memory");
+
+ qt->t = targets[i];
+ qt->port = ports->tcp_ports[j];
+
+ for (k=0; kowin[k].tv_sec = -1;
+
+ qt->owin_offset = 0;
+ qt->recvs = qt->trans = 0;
+
+ qt->num = 0;
+ qt->mean = qt->s_knuth = 0;
+
+ qt->family = -1;
+
+ qt->next = qtargbase;
+ qtargbase = qt;
+ }
+ }
+
+ // Initialise our raw sending socket
+ // Assume, for now, that all target packets will be sent on same
+ // ethernet device
+ if ((o.sendpref & PACKET_SEND_ETH) && targets[0]->ifType() == devt_ethernet) {
+ memcpy(eth.srcmac, targets[0]->SrcMACAddress(), 6);
+ memcpy(eth.dstmac, targets[0]->NextHopMACAddress(), 6);
+ if ((eth.ethsd = eth_open_cached(targets[0]->deviceName())) == NULL)
+ fatal("%s: Failed to open ethernet device (%s)", __FUNCTION__, targets[0]->deviceName());
+ rawsd = -1;
+ ethptr = ð
+ } else {
+ /* Init our raw socket */
+ if ((rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )
+ pfatal("socket troubles in qscan");
+ unblock_socket(rawsd);
+ broadcast_socket(rawsd);
+#ifndef WIN32
+ sethdrinclude(rawsd);
+#endif
+ ethptr = NULL;
+ eth.ethsd = NULL;
+ }
+
+
+ // Initialise our pcap descriptor
+
+ pd = my_pcap_open_live(targets[0]->deviceName(), 8192, (o.spoofsource)? 1 : 0, 1);
+
+ snprintf(pcap_filter, sizeof(pcap_filter), "tcp and dst host %s", inet_ntoa(targets[0]->v4source()));
+
+ if (o.debugging > 2) printf("Qscan pcap filter: %s\n", pcap_filter);
+ set_pcap_filter(targets[0]->deviceName(), pd, pcap_filter);
+
+
+
+ // Let's do it!
+
+ printf("Qscan parameters: round trips: %d, avg delay = %dms, confidence = %g\n", o.qscan_numtrips, o.qscan_delay, o.qscan_confidence);
+
+ SPM = new ScanProgressMeter("QScan");
+
+ qscan_run();
+
+ SPM->endTask(NULL, NULL);
+ delete SPM;
+
+ qscan_families();
+
+ printf(" Target:Port Fam uRTT +/- Stddev Loss (%%)\n");
+ for(qt = qtargbase; qt != NULL; qt=qt->next) {
+ if (qt->num == 0)
+ printf("%15s:%-5d ? N/A +/- N/A %3.0f\n", qt->t->targetipstr(), qt->port, 100* (1.0 - ((double)qt->recvs / qt->trans)));
+ else
+ printf("%15s:%-5d %c %5.1f +/- %5.1f %3.0f\n", qt->t->targetipstr(), qt->port, 'A'+qt->family, qt->mean, sqrt(qt->s_knuth/(qt->num-1)), 100* (1.0 - ((double)qt->recvs / qt->trans)));
+ }
+
+
+ // Clean up
+
+ pcap_close(pd);
+
+ if (rawsd < 0) close(rawsd);
+
+ for(qt = qtargbase; qt != NULL;) {
+ qt2 = qt->next;
+ free(qt);
+ qt = qt2;
+ }
+
+}