diff options
Diffstat (limited to '')
-rw-r--r-- | scan_engine.h | 691 |
1 files changed, 691 insertions, 0 deletions
diff --git a/scan_engine.h b/scan_engine.h new file mode 100644 index 0000000..3d49d15 --- /dev/null +++ b/scan_engine.h @@ -0,0 +1,691 @@ + +/*************************************************************************** + * scan_engine.h -- Includes much of the "engine" functions for scanning, * + * such as ultra_scan. It also includes dependent functions such as * + * those for collecting SYN/connect scan responses. * + * * + ***********************IMPORTANT NMAP LICENSE TERMS************************ + * + * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap + * Project"). Nmap is also a registered trademark of the Nmap Project. + * + * This program is distributed under the terms of the Nmap Public Source + * License (NPSL). The exact license text applying to a particular Nmap + * release or source code control revision is contained in the LICENSE + * file distributed with that version of Nmap or source code control + * revision. More Nmap copyright/legal information is available from + * https://nmap.org/book/man-legal.html, and further information on the + * NPSL license itself can be found at https://nmap.org/npsl/ . This + * header summarizes some key points from the Nmap license, but is no + * substitute for the actual license text. + * + * Nmap is generally free for end users to download and use themselves, + * including commercial use. It is available from https://nmap.org. + * + * The Nmap license generally prohibits companies from using and + * redistributing Nmap in commercial products, but we sell a special Nmap + * OEM Edition with a more permissive license and special features for + * this purpose. See https://nmap.org/oem/ + * + * If you have received a written Nmap license agreement or contract + * stating terms other than these (such as an Nmap OEM license), you may + * choose to use and redistribute Nmap under those terms instead. + * + * The official Nmap Windows builds include the Npcap software + * (https://npcap.com) for packet capture and transmission. It is under + * separate license terms which forbid redistribution without special + * permission. So the official Nmap Windows builds may not be redistributed + * without special permission (such as an Nmap OEM license). + * + * Source is provided to this software because we believe users have a + * right to know exactly what a program is going to do before they run it. + * This also allows you to audit the software for security holes. + * + * Source code also allows you to port Nmap to new platforms, fix bugs, and add + * new features. You are highly encouraged to submit your changes as a Github PR + * or by email to the dev@nmap.org mailing list for possible incorporation into + * the main distribution. Unless you specify otherwise, it is understood that + * you are offering us very broad rights to use your submissions as described in + * the Nmap Public Source License Contributor Agreement. This is important + * because we fund the project by selling licenses with various terms, and also + * because the inability to relicense code has caused devastating problems for + * other Free Software projects (such as KDE and NASM). + * + * The free version of Nmap is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties, + * indemnification and commercial support are all available through the + * Npcap OEM program--see https://nmap.org/oem/ + * + ***************************************************************************/ + +/* $Id$ */ + +#ifndef SCAN_ENGINE_H +#define SCAN_ENGINE_H + +#include "scan_lists.h" +#include "probespec.h" + +#include <dnet.h> + +#include "timing.h" + +#include <pcap.h> +#include <list> +#include <vector> +#include <set> +#include <algorithm> +class Target; + +/* 3rd generation Nmap scanning function. Handles most Nmap port scan types */ +void ultra_scan(std::vector<Target *> &Targets, const struct scan_lists *ports, + stype scantype, struct timeout_info *to = NULL); + +/* Determines an ideal number of hosts to be scanned (port scan, os + scan, version detection, etc.) in parallel after the ping scan is + completed. This is a balance between efficiency (more hosts in + parallel often reduces scan time per host) and results latency (you + need to wait for all hosts to finish before Nmap can spit out the + results). Memory consumption usually also increases with the + number of hosts scanned in parallel, though rarely to significant + levels. */ +int determineScanGroupSize(int hosts_scanned_so_far, + const struct scan_lists *ports); + +class UltraScanInfo; + +struct ppkt { /* Beginning of ICMP Echo/Timestamp header */ + u8 type; + u8 code; + u16 checksum; + u16 id; + u16 seq; +}; + +class ConnectProbe { +public: + ConnectProbe(); + ~ConnectProbe(); + int sd; /* Socket descriptor used for connection. -1 if not valid. */ +}; + +struct IPExtraProbeData_icmp { + u16 ident; +}; + +struct IPExtraProbeData_tcp { + u16 sport; + u32 seq; /* host byte order (like the other fields */ +}; + +struct IPExtraProbeData_udp { + u16 sport; +}; + +struct IPExtraProbeData_sctp { + u16 sport; + u32 vtag; +}; + +struct IPExtraProbeData { + u32 ipid; /* host byte order */ + union { + struct IPExtraProbeData_icmp icmp; + struct IPExtraProbeData_tcp tcp; + struct IPExtraProbeData_udp udp; + struct IPExtraProbeData_sctp sctp; + } pd; +}; + +union _tryno_u { + struct { + u8 isPing : 1; // Is this a ping, not a scanprobe? + u8 seqnum : 7; // Sequence number, 0-127 + } fields; + u8 opaque; +}; +typedef union _tryno_u tryno_t; + +/* At least for now, I'll just use this like a struct and access + all the data members directly */ +class UltraProbe { +public: + UltraProbe(); + ~UltraProbe(); + enum UPType { UP_UNSET, UP_IP, UP_CONNECT, UP_ARP, UP_ND } type; /* The type of probe this is */ + + /* Sets this UltraProbe as type UP_IP and creates & initializes the + internal IPProbe. The relevant probespec is necessary for setIP + because pspec.type is ambiguous with just the ippacket (e.g. a + tcp packet could be PS_PROTO or PS_TCP). */ + void setIP(const u8 *ippacket, u32 iplen, const probespec *pspec); + /* Sets this UltraProbe as type UP_CONNECT, preparing to connect to given + port number*/ + void setConnect(u16 portno); + /* Pass an arp packet, including ethernet header. Must be 42bytes */ + void setARP(const u8 *arppkt, u32 arplen); + void setND(const u8 *ndpkt, u32 ndlen); + // The 4 accessors below all return in HOST BYTE ORDER + // source port used if TCP, UDP or SCTP + u16 sport() const; + // destination port used if TCP, UDP or SCTP + u16 dport() const; + u32 ipid() const { + return probes.IP.ipid; + } + u16 icmpid() const; // ICMP ident if protocol is ICMP + u32 tcpseq() const; // TCP sequence number if protocol is TCP + u32 sctpvtag() const; // SCTP vtag if protocol is SCTP + /* Number, such as IPPROTO_TCP, IPPROTO_UDP, etc. */ + u8 protocol() const { + return mypspec.proto; + } + ConnectProbe *CP() const { + return probes.CP; // if type == UP_CONNECT + } + // Arpprobe removed because not used. + // ArpProbe *AP() { return probes.AP; } // if UP_ARP + // Returns the protocol number, such as IPPROTO_TCP, or IPPROTO_UDP, by + // reading the appropriate fields of the probespec. + + /* Get general details about the probe */ + const probespec *pspec() const { + return &mypspec; + } + + /* Returns true if the given tryno matches this probe. */ + bool check_tryno(u8 tryno) const { + return tryno == this->tryno.opaque; + } + + /* Helper for checking protocol/port match from a packet. */ + bool check_proto_port(u8 proto, u16 sport_or_icmpid, u16 dport) const; + + /* tryno/pingseq, depending on what type of probe this is (ping vs scanprobe) */ + tryno_t tryno; /* Try (retransmission) number of this probe */ + /* If true, probe is considered no longer active due to timeout, but it + may be kept around a while, just in case a reply comes late */ + bool timedout; + /* A packet may be timedout for a while before being retransmitted due to + packet sending rate limitations */ + bool retransmitted; + + struct timeval sent; + /* Time the previous probe was sent, if this is a retransmit (tryno > 0) */ + struct timeval prevSent; + bool isPing() const { + return tryno.fields.isPing; + } + u8 get_tryno() const { + return tryno.fields.seqnum; + } + +private: + probespec mypspec; /* Filled in by the appropriate set* function */ + union { + IPExtraProbeData IP; + ConnectProbe *CP; + // ArpProbe *AP; + } probes; +}; + +/* Global info for the connect scan */ +class ConnectScanInfo { +public: + ConnectScanInfo(); + ~ConnectScanInfo(); + + /* Watch a socket descriptor (add to fd_sets and maxValidSD). Returns + true if the SD was absent from the list, false if you tried to + watch an SD that was already being watched. */ + bool watchSD(int sd); + + /* Clear SD from the fd_sets and maxValidSD. Returns true if the SD + was in the list, false if you tried to clear an sd that wasn't + there in the first place. */ + bool clearSD(int sd); + /* Try to get a socket that's good for select(). Return true if it worked; + * false if it didn't. */ + bool sendOK(); + int maxValidSD; /* The maximum socket descriptor in any of the fd_sets */ + fd_set fds_read; + fd_set fds_write; + fd_set fds_except; + int numSDs; /* Number of socket descriptors being watched */ + int getSocket(); +private: + int nextSD; + int maxSocketsAllowed; /* No more than this many sockets may be created @once */ +}; + +class HostScanStats; + +/* These are ultra_scan() statistics for the whole group of Targets */ +class GroupScanStats { +public: + struct timeval timeout; /* The time at which we abort the scan */ + /* Most recent host tested for sendability */ + struct sockaddr_storage latestip; + GroupScanStats(UltraScanInfo *UltraSI); + ~GroupScanStats(); + void probeSent(unsigned int nbytes); + /* Returns true if the GLOBAL system says that sending is OK. */ + bool sendOK(struct timeval *when) const; + /* Total # of probes outstanding (active) for all Hosts */ + int num_probes_active; + UltraScanInfo *USI; /* The USI which contains this GSS. Use for at least + getting the current time w/o gettimeofday() */ + struct ultra_timing_vals timing; + struct timeout_info to; /* Group-wide packet rtt/timeout info */ + int numtargets; /* Total # of targets scanned -- includes finished and incomplete hosts */ + int numprobes; /* Number of probes/ports scanned on each host */ + /* The last time waitForResponses finished (initialized to GSS creation time */ + int probes_sent; /* Number of probes sent in total. This DOES include pings and retransmissions */ + + /* The most recently received probe response time -- initialized to scan + start time. */ + struct timeval lastrcvd; + /* The time the most recent ping was sent (initialized to scan begin time) */ + struct timeval lastping_sent; + /* Value of numprobes_sent at lastping_sent time -- to ensure that we don't + send too many pings when probes are going slowly. */ + int lastping_sent_numprobes; + + /* These two variables control minimum- and maximum-rate sending (--min-rate + and --max-rate). send_no_earlier_than is for --max-rate and + send_no_later_than is for --min-rate; they have effect only when the + respective command-line option is given. An attempt is made to keep the + sending rate within the interval, however for send_no_later_than it is not + guaranteed. */ + struct timeval send_no_earlier_than; + struct timeval send_no_later_than; + + /* The host to which global pings are sent. This is kept updated to be the + most recent host that was found up. */ + HostScanStats *pinghost; + + struct timeval last_wait; + int probes_sent_at_last_wait; + // number of hosts that timed out during scan, or were already timedout + int num_hosts_timedout; + ConnectScanInfo *CSI; +}; + +struct send_delay_nfo { + unsigned int delayms; /* Milliseconds to delay between probes */ + /* The number of successful and dropped probes since the last time the delay + was changed. The ratio controls when the rate drops. */ + unsigned int goodRespSinceDelayChanged; + unsigned int droppedRespSinceDelayChanged; + struct timeval last_boost; /* Most recent time of increase to delayms. Init to creation time. */ +}; + +/* To test for rate limiting, there is a delay in sending the first packet + of a certain retransmission number. These values help track that. */ +struct rate_limit_detection_nfo { + unsigned int max_tryno_sent; /* What is the max tryno we have sent so far (starts at 0) */ + bool rld_waiting; /* Are we currently waiting due to RLD? */ + struct timeval rld_waittime; /* if RLD waiting, when can we send? */ +}; + +/* The ultra_scan() statistics that apply to individual target hosts in a + group */ +class HostScanStats { +public: + Target *target; /* A copy of the Target that these stats refer to. */ + HostScanStats(Target *t, UltraScanInfo *UltraSI); + ~HostScanStats(); + bool freshPortsLeft() const; /* Returns true if there are ports remaining to probe */ + int numFreshPortsLeft() const; /* Returns the number of ports remaining to probe */ + int next_portidx; /* Index of the next port to probe in the relevant + ports array in USI.ports */ + bool sent_arp; /* Has an ARP probe been sent for the target yet? */ + + /* massping state. */ + /* The index of the next ACK port in o.ping_ackprobes to probe during ping + scan. */ + int next_ackportpingidx; + /* The index of the next SYN port in o.ping_synprobes to probe during ping + scan. */ + int next_synportpingidx; + /* The index of the next UDP port in o.ping_udpprobes to probe during ping + scan. */ + int next_udpportpingidx; + /* The index of the next SCTP port in o.ping_protoprobes to probe during ping + scan. */ + int next_sctpportpingidx; + /* The index of the next IP protocol in o.ping_protoprobes to probe during ping + scan. */ + int next_protoportpingidx; + /* Whether we have sent an ICMP echo request. */ + bool sent_icmp_ping; + /* Whether we have sent an ICMP address mask request. */ + bool sent_icmp_mask; + /* Whether we have sent an ICMP timestamp request. */ + bool sent_icmp_ts; + + /* Have we warned that we've given up on a port for this host yet? Only one + port per host is reported. */ + bool retry_capped_warned; + + void probeSent(unsigned int nbytes); + + /* How long I am currently willing to wait for a probe response + before considering it timed out. Uses the host values from + target if they are available, otherwise from gstats. Results + returned in MICROseconds. */ + unsigned long probeTimeout() const; + + /* How long I'll wait until completely giving up on a probe. + Timedout probes are often marked as such (and sometimes + considered a drop), but kept in the list juts in case they come + really late. But after probeExpireTime(), I don't waste time + keeping them around. Give in MICROseconds */ + unsigned long probeExpireTime(const UltraProbe *probe) const; + /* Returns OK if sending a new probe to this host is OK (to avoid + flooding). If when is non-NULL, fills it with the time that sending + will be OK assuming no pending probes are resolved by responses + (call it again if they do). when will become now if it returns + true. */ + bool sendOK(struct timeval *when) const; + + /* 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 nextTimeout(struct timeval *when) const; + UltraScanInfo *USI; /* The USI which contains this HSS */ + + /* Removes a probe from probes_outstanding, adjusts HSS and USS + active probe stats accordingly, then deletes the probe. */ + void destroyOutstandingProbe(std::list<UltraProbe *>::iterator probeI); + + /* Removes all probes from probes_outstanding using + destroyOutstandingProbe. This is used in ping scan to quit waiting + for responses once a host is known to be up. Invalidates iterators + pointing into probes_outstanding. */ + void destroyAllOutstandingProbes(); + + /* Mark an outstanding probe as timedout. Adjusts stats + accordingly. For connect scans, this closes the socket. */ + void markProbeTimedout(std::list<UltraProbe *>::iterator probeI); + + /* New (active) probes are appended to the end of this list. When a + host times out, it will be marked as such, but may hang around on + the list for a while just in case a response comes in. So use + num_probes_active to learn how many active (not timed out) probes + are outstanding. Probes on the bench (reached the current + maximum tryno and expired) are not counted in + probes_outstanding. */ + std::list<UltraProbe *> probes_outstanding; + /* The number of probes in probes_outstanding, minus the inactive (timed out) ones */ + unsigned int num_probes_active; + /* Probes timed out but not yet retransmitted because of congestion + control limits or because more retransmits may not be + necessary. Note that probes on probe_bench are not included + in this value. */ + unsigned int num_probes_waiting_retransmit; + unsigned int num_probes_outstanding() const { + return probes_outstanding.size(); + } + + /* The bench is a stock of probes (compacted into just the + probespec) that have met the current maximum tryno, and are on + ice until that tryno increases (so we can retransmit again), or + solidifies (so we can mark the port firewalled or whatever). The + tryno of bench members is bench_tryno. If the maximum tryno + increases, everyone on the bench is moved to the retry_stack. + */ + std::vector<probespec> probe_bench; + unsigned int bench_tryno; /* # tryno of probes on the bench */ + /* The retry_stack are probespecs that were on the bench but are now + slated to be retried. It is kept sorted such that probes with highest + retry counts are on top, ready to be taken first. */ + std::vector<probespec> retry_stack; + /* retry_stack_tries MUST BE KEPT IN SYNC WITH retry_stack. + retry_stack_tries[i] is the number of completed retries for the + probe in retry_stack[i] */ + std::vector<u8> retry_stack_tries; + /* tryno of probes on the retry queue */ + /* Moves the given probe from the probes_outstanding list, to + probe_bench, and decrements num_probes_waiting_retransmit accordingly */ + void moveProbeToBench(std::list<UltraProbe *>::iterator probeI); + /* Dismiss all probe attempts on bench -- the ports are marked + 'filtered' or whatever is appropriate for having no response */ + void dismissBench(); + /* Move all members of bench to retry_stack for probe retransmission */ + void retransmitBench(); + + bool completed() const; /* Whether or not the scan of this Target has completed */ + struct timeval completiontime; /* When this Target completed */ + + /* This function provides the proper cwnd and ssthresh 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 getTiming(struct ultra_timing_vals *tmng) const; + struct ultra_timing_vals timing; + /* The most recently received probe response time -- initialized to scan start time. */ + struct timeval lastrcvd; + struct timeval lastping_sent; /* The time the most recent ping was sent (initialized to scan begin time) */ + + /* Value of numprobes_sent at lastping_sent time -- to ensure that we + don't send too many pings when probes are going slowly. */ + int lastping_sent_numprobes; + struct timeval lastprobe_sent; /* Most recent probe send (including pings) by host. Init to scan begin time. */ + /* gives the maximum try number (try numbers start at zero and + increments for each retransmission) that may be used, based on + the scan type, observed network reliability, timing mode, etc. + This may change during the scan based on network traffic. If + capped is not null, it will be filled with true if the tryno is + at its upper limit. That often calls for a warning to be issued, + and marking of remaining timedout ports firewalled or whatever is + appropriate. If mayincrease is non-NULL, it is set to whether + the allowedTryno may increase again. If it is false, any probes + which have reached the given limit may be dealt with. */ + unsigned int allowedTryno(bool *capped, bool *mayincrease) const; + + /* Provides the next ping sequence number. This starts at zero, goes + up to 127, then wraps around back to 0. */ + u8 nextPingSeq() { + // Has to fit in 7 bits: tryno.fields.seqnum + nxtpseq = (nxtpseq + 1) % 0x80; + return nxtpseq; + } + /* This is the highest try number that has produced useful results + (such as port status change). */ + unsigned int max_successful_tryno; + int ports_finished; /* The number of ports of this host that have been determined */ + int numprobes_sent; /* Number of port probes (not counting pings, but counting retransmits) sent to this host */ + /* Boost the scan delay for this host, usually because too many packet + drops were detected. */ + void boostScanDelay(); + struct send_delay_nfo sdn; + struct rate_limit_detection_nfo rld; + +private: + u8 nxtpseq; /* the next scanping sequence number to use */ +}; + +/* A few extra performance tuning parameters specific to ultra_scan. */ +struct ultra_scan_performance_vars : public scan_performance_vars { + /* When a successful ping response comes back, it counts as this many + "normal" responses, because the fact that pings are necessary means + we aren't getting much input. */ + int ping_magnifier; + /* Try to send a scanping if no response has been received from a target host + in this many usecs */ + int pingtime; + unsigned int tryno_cap; /* The maximum trynumber (starts at zero) allowed */ + + void init(); +}; + +struct HssPredicate { +public: + int operator() (const HostScanStats *lhs, const HostScanStats *rhs) const; + static struct sockaddr_storage *ss; +}; + +class UltraScanInfo { +public: + UltraScanInfo(); + UltraScanInfo(std::vector<Target *> &Targets, const struct scan_lists *pts, stype scantype) { + Init(Targets, pts, scantype); + } + ~UltraScanInfo(); + /* Must call Init if you create object with default constructor */ + void Init(std::vector<Target *> &Targets, const struct scan_lists *pts, stype scantp); + + unsigned int numProbesPerHost() const; + + /* Consults with the group stats, and the hstats for every + incomplete hosts to determine whether any probes may be sent. + Returns true if they can be sent immediately. If when is non-NULL, + it is filled with the next possible time that probes can be sent + (which will be now, if the function returns true */ + bool sendOK(struct timeval *tv) const; + stype scantype; + bool tcp_scan; /* scantype is a type of TCP scan */ + bool udp_scan; + bool sctp_scan; /* scantype is a type of SCTP scan */ + bool prot_scan; + bool ping_scan; /* Includes trad. ping scan & arp scan */ + bool ping_scan_arp; /* ONLY includes arp ping scan */ + bool ping_scan_nd; /* ONLY includes ND ping scan */ + bool noresp_open_scan; /* Whether no response means a port is open */ + + /* massping state. */ + /* If ping_scan is true (unless ping_scan_arp is also true), this is the set + of ping techniques to use (ICMP, raw ICMP, TCP connect, raw TCP, or raw + UDP). */ + struct { + unsigned int rawicmpscan: 1, + connecttcpscan: 1, + rawtcpscan: 1, + rawudpscan: 1, + rawsctpscan: 1, + rawprotoscan: 1; + } ptech; + + bool isRawScan() const; + + struct timeval now; /* Updated after potentially meaningful delays. This can + be used to save a call to gettimeofday() */ + GroupScanStats *gstats; + struct ultra_scan_performance_vars perf; + /* A circular buffer of the incompleteHosts. nextIncompleteHost() gives + the next one. The first time it is called, it will give the + first host in the list. If incompleteHosts is empty, returns + NULL. */ + HostScanStats *nextIncompleteHost(); + /* Removes any hosts that have completed their scans from the incompleteHosts + list, and remove any hosts from completedHosts which have exceeded their + lifetime. Returns the number of hosts removed. */ + int removeCompletedHosts(); + /* Find a HostScanStats by its IP address in the incomplete and completed + lists. Returns NULL if none are found. */ + HostScanStats *findHost(struct sockaddr_storage *ss) const; + + double getCompletionFraction() const; + + unsigned int numIncompleteHosts() const { + return incompleteHosts.size(); + } + /* Call this instead of checking for numIncompleteHosts() == 0 because it + avoids a potential traversal of the list to find the size. */ + bool incompleteHostsEmpty() const { + return incompleteHosts.empty(); + } + bool numIncompleteHostsLessThan(unsigned int n) const; + + unsigned int numInitialHosts() const { + return numInitialTargets; + } + + void log_overall_rates(int logt) const; + void log_current_rates(int logt, bool update = true); + + /* Any function which messes with (removes elements from) + incompleteHosts may have to manipulate nextI */ + std::multiset<HostScanStats *, HssPredicate> incompleteHosts; + /* Hosts are moved from incompleteHosts to completedHosts as they are + completed. We keep them around because sometimes responses come back very + late, after we consider a host completed. */ + std::multiset<HostScanStats *, HssPredicate> completedHosts; + /* The last time we went through completedHosts to remove hosts */ + struct timeval lastCompletedHostRemoval; + + ScanProgressMeter *SPM; + PacketRateMeter send_rate_meter; + const struct scan_lists *ports; + int rawsd; /* raw socket descriptor */ + pcap_t *pd; + eth_t *ethsd; + u32 seqmask; /* This mask value is used to encode values in sequence + numbers. It is set randomly in UltraScanInfo::Init() */ + u16 base_port; + const struct sockaddr_storage *SourceSockAddr() const { return &sourceSockAddr; } + +private: + + unsigned int numInitialTargets; + std::multiset<HostScanStats *, HssPredicate>::iterator nextI; + // All targets in an invocation will have the same source address. + struct sockaddr_storage sourceSockAddr; + /* We encode per-probe information like the tryno in the source + port, for protocols that use ports. (Except when o.magic_port_set is + true--then we honor the requested source port.) The tryno is + encoded as offsets from base_port, a base source port number (see + sport_encode and sport_decode). To avoid interpreting a late response from a + previous invocation of ultra_scan as a response for the same port in the + current invocation, we increase base_port by a healthy amount designed to be + greater than any offset likely to be used by a probe, each time ultra_scan is + run. + + If we don't increase the base port, then there is the risk of something like + the following happening: + 1. Nmap sends an ICMP echo and a TCP ACK probe to port 80 for host discovery. + 2. Nmap receives an ICMP echo reply and marks the host up. + 3. Nmap sends a TCP SYN probe to port 80 for port scanning. + 4. Nmap finally receives a delayed TCP RST in response to its earlier ACK + probe, and wrongly marks port 80 as closed. */ + + /* Base port must be chosen so that there is room to add an 8-bit value (tryno) + * without exceeding 16 bits. We increment modulo the largest prime number N + * such that 33000 + N + 256 < 65536, which ensures no overlapping cycles. */ + // Nearest prime not exceeding 65536 - 256 - 33000: +#define PRIME_32K 32261 + /* Change base_port to a new number in a safe port range that is unlikely to + conflict with nearby past or future invocations of ultra_scan. */ + static u16 increment_base_port() { + static u16 g_base_port = 33000 + get_random_uint() % PRIME_32K; + g_base_port = 33000 + (g_base_port - 33000 + 256) % PRIME_32K; + return g_base_port; + } + +}; + +/* Whether this is storing timing stats for a whole group or an + individual host */ +enum ultra_timing_type { TIMING_HOST, TIMING_GROUP }; + +const char *pspectype2ascii(int type); + +void ultrascan_port_probe_update(UltraScanInfo *USI, HostScanStats *hss, + std::list<UltraProbe *>::iterator probeI, + int newstate, struct timeval *rcvdtime, + bool adjust_timing_hint = true); + +void ultrascan_host_probe_update(UltraScanInfo *USI, HostScanStats *hss, + std::list<UltraProbe *>::iterator probeI, + int newstate, struct timeval *rcvdtime, + bool adjust_timing_hint = true); + +void ultrascan_ping_update(UltraScanInfo *USI, HostScanStats *hss, + std::list<UltraProbe *>::iterator probeI, + struct timeval *rcvdtime, + bool adjust_timing = true); +#endif /* SCAN_ENGINE_H */ + |