Commit 144fe5cc authored by robertdavidgraham's avatar robertdavidgraham
Browse files

--offline, for benchmarking

parent a54f56aa
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ SYS := $(shell gcc -dumpmachine)
# works on the bajillion of different Linux environments
ifneq (, $(findstring linux, $(SYS)))
LIBS = -lpcap -lm -lrt -ldl -rdynamic -lpthread
INCLUDES = -I. -I../PF_RING/userland/lib
INCLUDES = -I.
FLAGS2 = 
endif

+9 −5
Original line number Diff line number Diff line
@@ -608,7 +608,7 @@ masscan_set_parameter(struct Masscan *masscan,
    } else if (EQUALS("banner1", name)) {
        banner1_test(value);
        exit(1);
    } else if (EQUALS("banners", name)) {
    } else if (EQUALS("banners", name) || EQUALS("banner", name)) {
        masscan->is_banners = 1;
    } else if (EQUALS("datadir", name)) {
        strcpy_s(masscan->nmap.datadir, sizeof(masscan->nmap.datadir), value);
@@ -667,6 +667,10 @@ masscan_set_parameter(struct Masscan *masscan,
    } else if (EQUALS("nmap", name)) {
        print_nmap_help();
        exit(1);
    } else if (EQUALS("offline", name)) {
        /* Run in "offline" mode where it thinks it's sending packets, but
         * it's not */
        masscan->is_offline = 1;
    } else if (EQUALS("open", name)) {
        masscan->nmap.open_only = 1;
    } else if (EQUALS("output-status", name)) {
@@ -687,7 +691,7 @@ masscan_set_parameter(struct Masscan *masscan,
        else {
            fprintf(stderr, "error: %s=%s\n", name, value);
        }
    } else if (EQUALS("output-filename", name)) {
    } else if (EQUALS("output-filename", name) || EQUALS("output-file", name)) {
        strcpy_s(masscan->nmap.filename, sizeof(masscan->nmap.filename), value);
    } else if (EQUALS("pcap", name)) {
        strcpy_s(masscan->pcap_filename, sizeof(masscan->pcap_filename), value);
@@ -715,7 +719,7 @@ masscan_set_parameter(struct Masscan *masscan,
        masscan->resume.seed = parseInt(value);
    } else if (EQUALS("resume-index", name)) {
        masscan->resume.index = parseInt(value);
    } else if (EQUALS("retries", name)) {
    } else if (EQUALS("retries", name) || EQUALS("retry", name)) {
        unsigned x = strtoul(value, 0, 0);
        if (x >= 1000) {
            fprintf(stderr, "error: retries=<n>: expected number less than 1000\n");
@@ -759,7 +763,7 @@ masscan_set_parameter(struct Masscan *masscan,
        return;
    } else if (EQUALS("source-port", name) || EQUALS("sourceport", name)) {
        masscan_set_parameter(masscan, "adapter-port", value);
    } else if (EQUALS("shard", name)) {
    } else if (EQUALS("shard", name) || EQUALS("shards", name)) {
        unsigned one = 0;
        unsigned of = 0;
        
@@ -846,7 +850,7 @@ is_singleton(const char *name)
        "no-stylesheet",
        "send-eth", "send-ip", "iflist", "randomize-hosts",
        "nmap", "trace-packet", "pfring", "sendq",
        "banners",
        "banners", "banner", "offline",
        0};
    size_t i;

+13 −8
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ masscan_initialize_adapter(struct Masscan *masscan,
     * Once we've figured out which adapter to use, we now need to
     * turn it on.
     */
    if (!masscan->is_offline) {
        masscan->adapter = rawsock_init_adapter(ifname, masscan->is_pfring, masscan->is_sendq);
        if (masscan->adapter == 0) {
            fprintf(stderr, "adapter[%s].init: failed\n", ifname);
@@ -112,6 +113,7 @@ masscan_initialize_adapter(struct Masscan *masscan,
        LOG(3, "rawsock: ignoring transmits\n");
        rawsock_ignore_transmits(masscan->adapter, adapter_mac);
        LOG(3, "rawsock: initialization done\n");
    }

    /*
     * ROUTER MAC ADDRESS
@@ -124,10 +126,13 @@ masscan_initialize_adapter(struct Masscan *masscan,
     * code above.
     */
    memcpy(router_mac, masscan->router_mac, 6);
    if (memcmp(router_mac, "\0\0\0\0\0\0", 6) == 0) {
    if (masscan->is_offline) {
        memcpy(router_mac, "\x66\x55\x44\x33\x22\x11", 6);
    } else if (memcmp(router_mac, "\0\0\0\0\0\0", 6) == 0) {
        unsigned router_ipv4;
        int err;


        LOG(1, "rawsock: looking for default gateway\n");
        err = rawsock_get_default_gateway(ifname, &router_ipv4);
        if (err == 0) {
+65 −36
Original line number Diff line number Diff line
@@ -7,6 +7,13 @@
    * main()
    * transmit_thread() - transmits probe packets
    * receive_thread() - receives response packets

    You'll be wanting to study the transmit/receive threads, because that's
    where all the action is.

    This is the lynch-pin of the entire program, so it includes a heckuva lot
    of headers, and the functions have a lot of local variables. I'm trying
    to make this file relative "flat" this way so that everything is visible.
*/
#include "masscan.h"

@@ -19,14 +26,13 @@
#include "main-throttle.h"      /* rate limit */
#include "main-dedup.h"         /* ignore duplicate responses */
#include "proto-arp.h"          /* for responding to ARP requests */
#include "proto-banner1.h"
#include "proto-banner1.h"      /* for snatching banners from systems */
#include "proto-tcp.h"          /* for TCP/IP connection table */
#include "syn-cookie.h"         /* for SYN-cookies on send */
#include "output.h"             /* for outputing results */
#include "rte-ring.h"           /* producer/consumer ring buffer */
#include "rawsock-pcapfile.h"   /* for saving pcap files w/ raw packets */
#include "smack.h"              /* Aho-corasick state-machine pattern-matcher */

#include "pixie-timer.h"        /* portable time functions */
#include "pixie-threads.h"      /* portable threads */
#include "proto-preprocess.h"   /* quick parse of packets */
@@ -61,7 +67,7 @@ flush_packets(struct Masscan *masscan, struct Throttler *throttler, uint64_t *pa
    while (!is_queue_empty) {
        /*
         * Only send a few packets at a time, throttled according to the max
         * --rate set by the usser
         * --max-rate set by the user
         */
        batch_size = throttler_next_batch(throttler, *packets_sent);

@@ -143,27 +149,33 @@ transmit_thread(void *v) /*aka. scanning_thread() */

    LOG(1, "xmit: starting transmit thread...\n");

    /* Create the shuffler/randomizer */
    /* Create the shuffler/randomizer. This creates the 'range' variable,
     * which is simply the number of IP addresses times the number of
     * ports */
    range = rangelist_count(&masscan->targets) 
            * rangelist_count(&masscan->ports);
    blackrock_init(&blackrock, range);

    /* Seed */
    /* This allows you to begin a scan somewhere other than the index
     * of zero (--seed). In the future. I might automatically seed this off
     * of thecurrent time automatically, but for the moment, I'm just 
     * starting from zero. */
    seed = masscan->seed;
    if (seed == 0 && masscan->shard.one == 1 && masscan->shard.of == 1)
        ; //seed = time(0) % range;

    /* start/end */
    /* Calculate the 'start' and 'end' of a scan. One reason to do this is
     * to support --shard, so that multiple machines can co-operate on
     * the same scan. Another reason to do this is so that we can bleed
     * a little bit past the end when we have --retries */
    if (masscan->resume.index != 0)
        start = masscan->resume.index;
    else
        start = (masscan->shard.one-1) * (range / masscan->shard.of);

    if (masscan->shard.of == 1)
        end = range;
    else
        end = masscan->shard.one * (range / masscan->shard.of);

    end += retries * rate;

    
@@ -179,12 +191,10 @@ transmit_thread(void *v) /*aka. scanning_thread() */
     * the scan */
    timestamp_start = 1.0 * pixie_gettime() / 1000000.0;


    /* TODO: this feature useless right now*/
    //seed = masscan->resume.seed;

    /* Optimize target selection so it's a quick binary search instead
     * of walking large memory tables */
     * of walking large memory tables. When we scan the entire Internet
     * our --excludefile will chop up our pristine 0.0.0.0/0 range into
     * hundreds of subranges. This scans through them faster. */
    picker = rangelist_pick2_create(&masscan->targets);

    /* -----------------
@@ -198,7 +208,7 @@ transmit_thread(void *v) /*aka. scanning_thread() */
         * Do a batch of many packets at a time. That because per-packet
         * throttling is expensive at 10-million pps, so we reduce the
         * per-packet cost by doing batches. At slower rates, the batch
         * size will always be one.
         * size will always be one. (--max-rate)
         */
        batch_size = throttler_next_batch(&throttler, packets_sent);
        packets_sent += batch_size;
@@ -218,11 +228,14 @@ transmit_thread(void *v) /*aka. scanning_thread() */
             *  order. Then, once we've shuffled the index, we "pick" the
             *  the IP address and port that the index refers to.
             */
            xXx = blackrock_shuffle(&blackrock, (i + (r--) * rate + seed) % range);
            xXx = (i + (r--) * rate + seed);
            while (xXx > range)
                xXx -= range;
            xXx = blackrock_shuffle(&blackrock,  xXx);
            ip = rangelist_pick2(&masscan->targets, xXx % count_ips, picker);
            port = rangelist_pick(&masscan->ports, xXx / count_ips);

            /* Print packet if debugging */
            /* Print --packet-trace if debugging */
            if (packet_trace)
                tcpkt_trace(pkt_template, ip, port, timestamp_start);

@@ -253,8 +266,8 @@ transmit_thread(void *v) /*aka. scanning_thread() */
             *  retransmits and sharding.
             */
            if (r == 0) {
                i++;
                r = retries + 1;
                i++; /* <--------- look at that puny increment */
                r = retries + 1; /* --retries */
            }

            /*
@@ -266,11 +279,11 @@ transmit_thread(void *v) /*aka. scanning_thread() */

        } /* end of batch */

        /* Transmit packets from other thread. */
        /* Transmit packets from other thread, when doing --banners */
        flush_packets(masscan, &throttler, &packets_sent);

        /* If the user pressed <ctrl-c>, then we need to exit. but, in case
         * the user wants to resume the scan later, we save the current
         * the user wants to --resume the scan later, we save the current
         * state in a file */
        if (control_c_pressed) {
            masscan->resume.seed = seed;
@@ -334,7 +347,7 @@ receive_thread(struct Masscan *masscan,


    /*
     * If configured, open a pcap file for saving raw packets. This is
     * If configured, open a --pcap file for saving raw packets. This is
     * so that we can debug scans, but also so that we can look at the
     * strange things people send us. Note that we don't record transmitted
     * packets, just the packets we've received.
@@ -343,7 +356,8 @@ receive_thread(struct Masscan *masscan,
        pcapfile = pcapfile_openwrite(masscan->pcap_filename, 1);

    /*
     * Open output. This is where results are reported.
     * Open output. This is where results are reported when saving
     * the --output-format to the --output-filename
     */
    out = output_create(masscan);

@@ -355,7 +369,7 @@ receive_thread(struct Masscan *masscan,

    /*
     * Create a TCP connection table for interacting with live
     * connections
     * connections when doing --banners
     */
    if (masscan->is_banners) {
        tcpcon = tcpcon_create_table(
@@ -368,6 +382,12 @@ receive_thread(struct Masscan *masscan,
            );
    }

    if (masscan->is_offline) {
        while (!masscan->is_done)
            pixie_usleep(10000);
        return;
    }

    /*
     * Receive packets. This is where we catch any responses and print
     * them to the terminal.
@@ -387,6 +407,12 @@ receive_thread(struct Masscan *masscan,
        unsigned seqno_them;
        unsigned seqno_me;


        /*
         * RECIEVE
         *
         * This is the boring part of actually receiving a packet
         */
        err = rawsock_recv_packet(
                    masscan->adapter,
                    &length,
@@ -400,7 +426,7 @@ receive_thread(struct Masscan *masscan,
        /*
         * Do any TCP event timeouts based on the current timestamp from
         * the packet. For example, if the connection has been open for
         * around 10 seconds, we'll close the connection.
         * around 10 seconds, we'll close the connection. (--banners)
         */
        if (tcpcon) {
            tcpcon_timeouts(tcpcon, secs, usecs);
@@ -427,7 +453,9 @@ receive_thread(struct Masscan *masscan,
            continue;


        /* OOPS: handle arp instead */
        /* OOPS: handle arp instead. Since we may completely bypass the TCP/IP
         * stack, we may have to handle ARPs ourself, or the router will 
         * lose track of us. */
        if (parsed.found == FOUND_ARP) {
            LOG(2, "found arp 0x%08x\n", parsed.ip_dst);

@@ -446,7 +474,7 @@ receive_thread(struct Masscan *masscan,
        if (adapter_port != parsed.port_dst)
            continue;

        /* Save raw packet (if configured to do so) */
        /* Save raw packet in --pcap file */
        if (pcapfile) {
            pcapfile_writeframe(
                pcapfile,
@@ -457,12 +485,12 @@ receive_thread(struct Masscan *masscan,
                usecs);
        }

        LOG(1, "%u.%u.%u.%u - ackno=0x%08x flags=%02x\n", 
        LOG(5, "%u.%u.%u.%u - ackno=0x%08x flags=%02x\n", 
            (ip_them>>24)&0xff, (ip_them>>16)&0xff, (ip_them>>8)&0xff, (ip_them>>0)&0xff, 
            seqno_me, TCP_FLAGS(px, parsed.transport_offset));


        /* If recording banners, create a new "TCP Control Block (TCB)" */
        /* If recording --banners, create a new "TCP Control Block (TCB)" */
        if (tcpcon) {
            struct TCP_Control_Block *tcb;

@@ -551,10 +579,7 @@ receive_thread(struct Masscan *masscan,
                continue;

            /*
             * XXXX
             * TODO: add lots more verification, such as coming from one of
             * our sending port numbers, and having the right seqno/ackno
             * fields set.
             * This is where we do the output
             */
            output_report(
                        out,
@@ -579,16 +604,22 @@ receive_thread(struct Masscan *masscan,
        pcapfile_close(pcapfile);
}


/***************************************************************************
 * We trap the <ctrl-c> so that instead of exiting immediately, we sit in
 * a loop for a few seconds waiting for any late response. But, the user
 * can press <ctrl-c> a second time to exit that waiting.
 ***************************************************************************/
static void control_c_handler(int x)
{
    control_c_pressed = 1+x;
}


/***************************************************************************
 * Start the scan. This is the main function of the program.
 * Called from main()
 * Called from main() to initiate the scan.
 * Launches the 'transmit_thread()' and 'receive_thread()' and waits for
 * them to exit.
 ***************************************************************************/
static int
main_scan(struct Masscan *masscan)
@@ -831,13 +862,11 @@ int main(int argc, char *argv[])
            x += tcpkt_selftest();
            x += ranges_selftest();
            x += pixie_time_selftest();
            //x += xring_selftest();
            x += rte_ring_selftest();
            x += smack_selftest();
            x += banner1_selftest();



            if (x != 0) {
                /* one of the selftests failed, so return error */
                fprintf(stderr, "regression test: failed :( \n");
+4 −3
Original line number Diff line number Diff line
@@ -89,9 +89,10 @@ struct Masscan
     */
    unsigned retries;

    unsigned is_pfring:1;
    unsigned is_sendq:1;
    unsigned is_banners:1;
    unsigned is_pfring:1;       /* --pfring */
    unsigned is_sendq:1;        /* --sendq */
    unsigned is_banners:1;      /* --banners */
    unsigned is_offline:1;      /* --offline */

    /**
     * Wait forever for responses, instead of the default 10 seconds
Loading