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
Makefile is included in the package, so simply type "make all" to compile the code.
However, it is build on several libraries (-lpthread -lgnutls -lbind -lssl -lcrypto -lresolv), please make sure you have those library installed before compiling the code
Besides, the code is tested only on Fedora 20.  It might not work on other Linux version.

3. run the code
run ./dns_query -h to get the following help information.
usage: ./dns_query
 -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
 -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. 
Let's assume the file is "names.txt"

a) query over UDP
To query all the DNS names in "names.txt", run: 
./dns_query -f names.txt -r your_resolver_IP -p your_resolver_port
By default, the program queries all the DNS names in "names.txt" by UDP. 

b) query with different protocols
You can test the query with other protocols by setting the -t options. 
Available options are "tcp/udp/tls/ssl/ptcp/cudp/ptls/ptcpnp/ptlsnp/pssl"
For example, to use TCP:
./dns_query -f names.txt -r your_resolver_IP -p your_resolver_port -t tcp
to use TLS:
./dns_query -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:
./dns_query -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:
./dns_query -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:
./dns_query -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
Finally, you can send queries over TLS directly to resolver without the TLS negotiation by set the "-e" option.  
By default, the code will perform TLS negotiation (sending the dummy query) first to test if the recursive resolver supports TLS or not.
For example:
./dns_query -f names.txt -r your_resolver_IP -p your_resolver_port -t ssl -e

