Matteo Monti
Matteo Monti

Reputation: 8950

DNS over UDP example query

I often find myself in need to test if an internet connection is online or not. In particular, sometimes it happens (on very, very peculiar connections) that UDP is disabled. Now, I figured that one of the most simple ways to test if UDP is available to my connection is through a DNS query.

Now, using some function like getaddrinfo abstracts away UDP from the query, so that (as far as my understanding goes) if UDP is not available, TCP will be used instead. Now, since I need to test for UDP connections, I will need to forge the UDP packet with the query myself. Moreover, I would like to make the query to a public DNS server (like 8.8.8.8), so that I am certain that the UDP connection is available to talk to external hosts.

So I am wondering: what is the most simple DNS query that I can send via an UDP packet? Could you show me an example that just asks for the ip, say, of google.com to a DNS server?

Upvotes: 2

Views: 1458

Answers (1)

abligh
abligh

Reputation: 25129

I'm not sure I understand your question fully, but the simplest query would be something like SOA for . (i.e. the start of authority for the root zone), like this:

$ dig SOA . @8.8.8.8

; <<>> DiG 9.8.3-P1 <<>> SOA . @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46366
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;.              IN  SOA

;; ANSWER SECTION:
.           4350    IN  SOA a.root-servers.net. nstld.verisign-grs.com. 2015102500 1800 900 604800 86400

;; Query time: 36 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Oct 25 21:07:19 2015
;; MSG SIZE  rcvd: 92

If you are asking what that looks like as a UDP packet, simply capture it with tcpdump. However, such trivial DNS packets are relatively easy to construct in C - see RFC1035. You may want to use a pre-existing library like c-ares or adns.

Note that as far as I remember, whether your resolver library falls back to TCP is implementation dependent. IIRC glibc on linux does not fall back to TCP, and libresolv on OpenBSD only does if /etc/resolv.conf contains options tcp. When using libresolv programatically you merely need to ensure RES_USEVC is clear.

If you are looking for example code, 'Stevens' TCP/IP illustrated' is the canonical answer.

Upvotes: 3

Related Questions