There are a number of utilities for making DNS queries manually, such as nslookup, host, and dig. I'll use dig in the following discussion, mainly because it automatically decodes and displays the entire content of DNS messages and its output is designed to resemble the DNS zone file format used by the BIND DNS server which will be discussed later.
Here's an example dig query:
$ dig ilab2.ilab.cs.uoregon.edu
; <<>> DiG 9.2.4 <<>> ilab2.ilab.cs.uoregon.edu ;; global options: printcmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14787 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 2 ;; QUESTION SECTION: ;ilab2.ilab.cs.uoregon.edu. IN A ;; ANSWER SECTION: ilab2.ilab.cs.uoregon.edu. 68214 IN A 128.223.203.2 ;; AUTHORITY SECTION: ilab.cs.uoregon.edu. 68214 IN NS dns.cs.uoregon.edu. ilab.cs.uoregon.edu. 68214 IN NS ilab2.ilab.cs.uoregon.edu. ilab.cs.uoregon.edu. 68214 IN NS phloem.uoregon.edu. ;; ADDITIONAL SECTION: dns.cs.uoregon.edu. 86400 IN A 128.223.6.9 phloem.uoregon.edu. 86400 IN A 128.223.32.35 ;; Query time: 51 msec ;; SERVER: 128.223.32.35#53(128.223.32.35) ;; WHEN: Mon Aug 1 18:57:04 2005 ;; MSG SIZE rcvd: 144
Note that dig prints data about each of the four portions of a DNS message. The query section shows the query name, query class (IN for Internet data), and query type (A for the default IPv4 address query). Replies contain a domain name, the time-to-live for that resource record (in seconds), class, and a resource record type and value.
dig can be used to query for a specific resource record type (or any to get all resource records for a name):
dig ilab.cs.uoregon.edu mx
Or to query a specific name server:
dig ilab2.ilab.cs.uoregon.edu @dns.cs.uoregon.edu
These and other options are useful for debugging, such as to see whether particular name servers agree on record values.
Programs typically use the gethostbyname() library function to resolve domain names, which typically is capable of using both local host tables like /etc/hosts and DNS in a configurable order (via /etc/nsswitch.conf) but programs can also call DNS-only resolver routines directly via the res_* functions (see res_query(3) and its related functions).