
digit
-----

1. introduction

This code is a DNS tool to perform DNS query with different protocols
such as UDP, TCP, TLS.  It supports TCP/TLS connection reuse, query
pipelining. For TLS, it supports both gnutls and OpenSSL.  It also
supports using TCP fast open. see the examples at the end of this doc.


2. compile the code

a)

Digit now uses autoconf.  See INSTALL for how to build it.

We build it on Fedora-20, where it requires these packages:
   libbind-devel
   openssl-devel
xxx.
(-lpthread -lgnutls -lbind -lssl -lcrypto -lresolv)

It should build on other Unixes with similar libraries.

b) If you build it from the source tree, bootstrap with:
   autoreconf --install
   ./configure
   make

3. run the code

run ./digit -h to get the following help information.

usage: ./digit
 -f/--dnslist-file = file, file contains a list of DNS names
 -r/--dns-resolver = resolver ip, dns resolver ip
 -d/--disable-nagle, disable nagle
 -v/--validate-ca, validate CA
 -o/--enable-tcpfast, enable TCP fastopen
 -n/--num-queries = number, total number of queries to send
 -p/--port-number = port, dns server port number
 -t/--protocol = protocol, could be tcp/udp/tls/ssl/ptcp/cudp/ptls/ptcpnp/ptlsnp/pssl
 -i/--interval = ms, interval between queries
 -e/--direct-tls, send query over tls, without the dummy edns query
 -V/--verbose, print details of responses (if not specified, we only print latency stats)
 -h/--help, show this message

to run the code, you need to put all the DNS names that you want to query in a file, one domain per line. 
Let's assume the file is "names.txt". The code with perform dns query for each domain in "names.txt" and output some stats information.
sample data in "names.txt":
    www.google.com
    www.facebook.com

the output fsdb schema is
    #fsdb   index   t_complete  t_avg   t_individual    t_sum   t_mean  id  query_send_ts   response_receive_ts program_start_ts
where:
    index: query index
    t_complete: time elapsed when all queries got responses. 
    t_avg: equals to t_complete/(# of queries)
    t_individual: time used for each query ( equals to response_receive_ts - query_send_ts)
    t_sum: sum(t_individual)
    t_mean: equals to t_sum//(# of queries)
    id: dns ID used in the query
    query_send_ts: timestamp when the query is sent
    response_receive_ts: timestamp when the response for this query is received.
    program_start_ts: timestamp when the program is started
    
sample output:
    #fsdb   index   t_complete  t_avg   t_individual    t_sum   t_mean  id  query_send_ts   response_receive_ts program_start_ts
    1   0.096254    0.096254    0.096254    0.096254    0.096254    19383   1414541062.314742   1414541062.410995   1414541062.314741
    2   0.254078    0.127039    0.157802    0.254056    0.127028    19384   1414541062.411016   1414541062.568818   1414541062.314741
    
you can also use -V option to print detailed information in responses 


4. examples
Below are a few examples of using digit to perform DNS queries:
    a) query over UDP
        To query all DNS names in "names.txt", run: 
        ./digit -f names.txt -r your_resolver_IP -p your_resolver_port
        By default, the program queries all DNS names in "names.txt" via UDP. 
    
    b) query with different protocols
        You can test the query with other protocols by setting the -t options. 
        Available options for -t are "tcp/udp/tls/ssl/ptcp/cudp/ptls/ptcpnp/ptlsnp/pssl"
        For example, to do query over TCP:
        ./digit -f names.txt -r your_resolver_IP -p your_resolver_port -t tcp
        to do query over TLS:
        ./digit -f names.txt -r your_resolver_IP -p your_resolver_port -t TLS
        The difference between "ssl" and "tls" options: when using "tls", the session is built with gnutls, while the session is built with OpenSSl when using "ssl"
        
        "ptcp" makes the code to reuse tcp connection, all the queries are sent over the same tcp connection back to back.
        For example:
        ./digit -f names.txt -r your_resolver_IP -p your_resolver_port -t ptcp
        
        Both "ptcp" and "ptcpnp" reuse the tcp connection.
        The difference is: 
        "ptcp" pipelines all the query back to back, but "ptcpnp" doesn't do pipelining, it sends one query, then wait for response before sending the next query. 
        similarly, you should be able to guess the meaning of "pssl/psslnp" and "ptls/ptlsnp".
    
    c) enable certificate validation
        you can set the "-v" option to turn on certificate validation. 
        For example:
        ./digit -f names.txt -r your_resolver_IP -p your_resolver_port -t TLS -v
        However, make sure you have CAFILE in the right place:
        Right now the location of CAFILE is hard-coded in the code (in the file dns_query.cc)
        #define CAFILE "/etc/ssl/certs/ca-bundle.trust.crt"
    
    d) enable TCP fastopen
        you can set the the "-o" option to enable TCP fastopen. 
        For example:
        ./digit -f names.txt -r your_resolver_IP -p your_resolver_port -t tcp -o
        However, you must first have TCP fastopen enabled in the kernel on your machine
        refer to "http://edsiper.linuxchile.cl/blog/2013/02/21/linux-tcp-fastopen-in-your-sockets/" for how to enable TCP fastopen in the kernel.
    
    e) disable TLS negotiation
        You can also send queries over TLS directly to resolver without the TLS negotiation with the "-e" option.  
        By default, the tool will perform TLS negotiation (sending the dummy query with TO bit set) first to test if the recursive resolver supports TLS or not.
        For example:
        ./digit -f names.txt -r your_resolver_IP -p your_resolver_port -t ssl -e
