📄 osscan2.cc
字号:
OFProbe *probe = *probeI; probesActive.erase(probeI); delete probe;}/* Get an active probe from active probe list identified by probe type and subid. Returns probesActive.end() if there isn't one */list<OFProbe *>::iterator HostOsScanStats::getActiveProbe(OFProbeType type, int subid) { list<OFProbe *>::iterator probeI; OFProbe *probe = NULL; for(probeI = probesActive.begin(); probeI != probesActive.end(); probeI++) { probe = *probeI; if(probe->type == type && probe->subid == subid) break; } if(probeI == probesActive.end()) { /* not found!? */ if(o.debugging > 1) log_write(LOG_PLAIN, "Probe doesn't exist! Probe type: %d. Probe subid: %d\n", type, subid); return probesActive.end(); } return probeI;}/* Move a probe from probesToSend to probesActive. */void HostOsScanStats::moveProbeToActiveList(list<OFProbe *>::iterator probeI) { probesActive.push_back(*probeI); probesToSend.erase(probeI);}/* Move a probe from probesActive to probesToSend. */void HostOsScanStats::moveProbeToUnSendList(list<OFProbe *>::iterator probeI) { probesToSend.push_back(*probeI); probesActive.erase(probeI);} /* Compute the ratio of amount of time taken between sending 1st TSEQ probe and 1st ICMP probe compared to the amount of time it should have taken. Ratios far from 1 can cause bogus results */double HostOsScanStats::timingRatio() { if (openTCPPort < 0) return 0; int msec_ideal = OS_SEQ_PROBE_DELAY * (NUM_SEQ_SAMPLES - 1); int msec_taken = TIMEVAL_MSEC_SUBTRACT(seq_send_times[NUM_SEQ_SAMPLES -1 ], seq_send_times[0]); if (o.debugging) { log_write(LOG_PLAIN, "OS detection timingRatio() == (%.3f - %.3f) * 1000 / %d == %.3f\n", seq_send_times[NUM_SEQ_SAMPLES - 1].tv_sec + seq_send_times[NUM_SEQ_SAMPLES - 1].tv_usec / 1000000.0, seq_send_times[0].tv_sec + (float) seq_send_times[0].tv_usec / 1000000.0, msec_ideal, (float) msec_taken / msec_ideal); } return (double) msec_taken / msec_ideal;}/* If there are pending probe timeouts, fills in when with the time of * the earliest one and returns true. Otherwise returns false and * puts now in when. */bool HostOsScan::nextTimeout(HostOsScanStats *hss, struct timeval *when) { assert(hss); struct timeval probe_to, earliest_to; list<OFProbe *>::iterator probeI; bool firstgood = true; assert(when); memset(&probe_to, 0, sizeof(probe_to)); memset(&earliest_to, 0, sizeof(earliest_to)); for(probeI = hss->probesActive.begin(); probeI != hss->probesActive.end(); probeI++) { TIMEVAL_ADD(probe_to, (*probeI)->sent, timeProbeTimeout(hss)); if (firstgood || TIMEVAL_SUBTRACT(probe_to, earliest_to) < 0) { earliest_to = probe_to; firstgood = false; } } *when = (firstgood)? now : earliest_to; return (firstgood)? false : true;}void HostOsScan::adjust_times(HostOsScanStats *hss, OFProbe *probe, struct timeval *rcvdtime) { assert(hss); assert(probe); /* Adjust timing */ if(rcvdtime) { adjust_timeouts2(&(probe->sent), rcvdtime, &(hss->target->to)); adjust_timeouts2(&(probe->sent), rcvdtime, &(stats->to)); } hss->timing.num_updates++; stats->timing.num_updates++; /* Adjust window */ if (probe->tryno > 0 || !rcvdtime) { if (TIMEVAL_SUBTRACT(probe->sent, hss->timing.last_drop) > 0) { hss->timing.cwnd = perf.low_cwnd; hss->timing.ccthresh = (int) MAX(hss->numProbesActive() / perf.host_drop_ccthresh_divisor, 2); hss->timing.last_drop = now; } if (TIMEVAL_SUBTRACT(probe->sent, stats->timing.last_drop) > 0) { stats->timing.cwnd = MAX(perf.low_cwnd, stats->timing.cwnd / perf.group_drop_cwnd_divisor); stats->timing.ccthresh = (int) MAX(stats->num_probes_active / perf.group_drop_ccthresh_divisor, 2); stats->timing.last_drop = now; } } else { /* Good news -- got a response to first try. Increase window as appropriate. */ if (hss->timing.cwnd <= hss->timing.ccthresh) { /* In quick start mode */ hss->timing.cwnd += perf.quick_incr; } else { /* Congestion control mode */ hss->timing.cwnd += perf.cc_incr / hss->timing.cwnd; } if (hss->timing.cwnd > perf.max_cwnd) hss->timing.cwnd = perf.max_cwnd; if (stats->timing.cwnd <= stats->timing.ccthresh) { /* In quick start mode */ stats->timing.cwnd += perf.quick_incr; } else { /* Congestion control mode */ stats->timing.cwnd += perf.cc_incr / stats->timing.cwnd; } if (stats->timing.cwnd > perf.max_cwnd) stats->timing.cwnd = perf.max_cwnd; }}ScanStats::ScanStats() { /* init timing val */ timing.cwnd = perf.group_initial_cwnd; timing.ccthresh = perf.initial_ccthresh; /* Will be reduced if any packets are dropped anyway */ timing.num_updates = 0; gettimeofday(&timing.last_drop, NULL); initialize_timeout_info(&to); num_probes_active = 0; num_probes_sent = num_probes_sent_at_last_wait = 0;}/* Returns true if the os scan system says that sending is OK.*/bool ScanStats::sendOK() { if (num_probes_sent - num_probes_sent_at_last_wait >= 50) return false; if (timing.cwnd < num_probes_active + 0.5) return false; return true;}HostOsScan::HostOsScan(Target *t) { pd = NULL; rawsd = -1; if ((o.sendpref & PACKET_SEND_ETH) && t->ifType() == devt_ethernet) { memcpy(eth.srcmac, t->SrcMACAddress(), 6); memcpy(eth.dstmac, t->NextHopMACAddress(), 6); if ((eth.ethsd = eth_open_cached(t->deviceName())) == NULL) fatal("%s: Failed to open ethernet device (%s)", __func__, t->deviceName()); rawsd = -1; ethptr = ð } else { /* Init our raw socket */ if ((rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 ) pfatal("socket troubles in %s", __func__); unblock_socket(rawsd); broadcast_socket(rawsd);#ifndef WIN32 sethdrinclude(rawsd);#endif ethptr = NULL; eth.ethsd = NULL; } tcpPortBase = o.magic_port_set? o.magic_port : o.magic_port + get_random_u8(); udpPortBase = o.magic_port_set? o.magic_port : o.magic_port + get_random_u8(); reInitScanSystem(); stats = new ScanStats();}HostOsScan::~HostOsScan() { if (rawsd >= 0) { close(rawsd); rawsd = -1; } if (pd) { pcap_close(pd); pd = NULL; } /* * No need to close ethptr->ethsd due to caching * if (eth.ethsd) { eth_close(eth.ethsd); eth.ethsd = NULL; } */ delete stats;}void HostOsScan::reInitScanSystem() { tcpSeqBase = get_random_u32(); tcpAck = get_random_u32(); tcpMss = 265; icmpEchoId = get_random_u16(); icmpEchoSeq = 295; udpttl = (time(NULL) % 14) + 51;}/* Initiate seq probe list */void HostOsScan::buildSeqProbeList(HostOsScanStats *hss) { assert(hss); int i; if(hss->openTCPPort == -1) return; if(hss->FP_TSeq) return; for(i=0; i<NUM_SEQ_SAMPLES; i++) hss->addNewProbe(OFP_TSEQ, i);}/* Update the seq probes in the active probe list: * o Remove the timedout seq probes. */void HostOsScan::updateActiveSeqProbes(HostOsScanStats *hss) { assert(hss); list<OFProbe *>::iterator probeI, nxt; OFProbe *probe = NULL; for(probeI = hss->probesActive.begin(); probeI != hss->probesActive.end(); probeI = nxt) { nxt = probeI; nxt++; probe = *probeI; /* Is the probe timedout? */ if (TIMEVAL_SUBTRACT(now, probe->sent) > (long) timeProbeTimeout(hss)) { hss->removeActiveProbe(probeI); stats->num_probes_active--; } }}/* initiate the normal tcp/udp/icmp probe list */void HostOsScan::buildTUIProbeList(HostOsScanStats *hss) { assert(hss); int i; /* The order of these probes are important for ipid generation * algorithm test and should not be changed. * * At doSeqTests we sent 6 TSeq probes to generate 6 tcp replies, * and here we follow with 3 probes to generate 3 icmp replies. In * this way we can expect to get "good" IPid sequence. * * **** Should be done in a more elegant way. ***** */ /* ticmp */ if(!hss->FP_TIcmp) { for(i=0; i<2; i++) { hss->addNewProbe(OFP_TICMP, i); } } /* tudp */ if(!hss->FP_TUdp) { hss->addNewProbe(OFP_TUDP, 0); } if(hss->openTCPPort != -1) { /* tops/twin probes. We send the probe again if we didn't get a response by the corresponding seq probe. */ if(!hss->FP_TOps || !hss->FP_TWin) { for(i=0; i<6; i++) { if(!hss->TOps_AVs[i] || !hss->TWin_AVs[i]) hss->addNewProbe(OFP_TOPS, i); } } /* tecn */ if(!hss->FP_TEcn) { hss->addNewProbe(OFP_TECN, 0); } /* t1_7: t1_t4 */ for(i=0; i<4; i++) { if(!hss->FPtests[FP_T1_7_OFF+i]) { hss->addNewProbe(OFP_T1_7, i); } } } /* t1_7: t5_t7 */ for(i=4; i<7; i++) { if(!hss->FPtests[FP_T1_7_OFF+i]) { hss->addNewProbe(OFP_T1_7, i); } }}/* Update the probes in the active probe list: * 1) Remove the expired probes (timedout and reached the retry limit); * 2) Move timedout probes to probeNeedToSend; */void HostOsScan::updateActiveTUIProbes(HostOsScanStats *hss) { assert(hss); list<OFProbe *>::iterator probeI, nxt; OFProbe *probe = NULL; for(probeI = hss->probesActive.begin(); probeI != hss->probesActive.end(); probeI = nxt) { nxt = probeI; nxt++; probe = *probeI; if(TIMEVAL_SUBTRACT(now, probe->sent) > (long) timeProbeTimeout(hss)) { if(probe->tryno >= 3) { /* The probe is expired. */ hss->removeActiveProbe(probeI); stats->num_probes_active--; } else { /* It is timedout, move it to the sendlist */ hss->moveProbeToUnSendList(probeI); stats->num_probes_active--; } } }}/* Check whether the host is sendok. If not, fill _when_ with the time * when it will be sendOK and return false; else, fill it with now and * return true. */bool HostOsScan::hostSendOK(HostOsScanStats *hss, struct timeval *when) { assert(hss); list<OFProbe *>::iterator probeI; int packTime; struct timeval probe_to, earliest_to, sendTime; long tdiff; if (hss->target->timedOut(&now)) { if (when) *when = now; return false; } if (hss->sendDelayMs > 0) { packTime = TIMEVAL_MSEC_SUBTRACT(now, hss->lastProbeSent); if (packTime < (int) hss->sendDelayMs) { if (when) { TIMEVAL_MSEC_ADD(*when, hss->lastProbeSent, hss->sendDelayMs); } return false; } } if (hss->timing.cwnd >= hss->numProbesActive() + .5) { if (when) *when = now; return true; } if (!when) return false; TIMEVAL_MSEC_ADD(earliest_to, now, 10000); /* Any timeouts coming up? */ for(probeI = hss->probesActive.begin(); probeI != hss->probesActive.end(); probeI++) { TIMEVAL_MSEC_ADD(probe_to, (*probeI)->sent, timeProbeTimeout(hss) / 1000); if (TIMEVAL_SUBTRACT(probe_to, earliest_to) < 0) { earliest_to = probe_to; } } // Will any scan delay affect this? if (hss->sendDelayMs > 0) { TIMEVAL_MSEC_ADD(sendTime, hss->lastProbeSent, hss->sendDelayMs); if (TIMEVAL_MSEC_SUBTRACT(sendTime, now) < 0) sendTime = now; tdiff = TIMEVAL_MSEC_SUBTRACT(earliest_to, sendTime); /* Timeouts previous to the sendTime requirement are pointless, and those later than sendTime are not needed if we can send a new packet at sendTime */ if (tdiff < 0) { earliest_to = sendTime;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -