I'm writing a DNS client in C that can issue DNS queries to a recursive DNS server and read the result. I'm currently reading RFC 1035 and looking at the output of DIG in tcpdump. I notice that in the hexdump of DNS queries, it would appear that the ARCOUNT field is set to 1, with QDCOUNT. However, ANCOUNT and NSCOUNT are zeroed.
I know that an IP header is 20 bytes, a UDP header is 8 bytes, and therefore the DNS header starts at 0x266e with an ID of 9838 - as shown on the output of DIG. Then, 0x120 is the tuple (QR, OPCODE, etc..) with QDCOUNT starting on the row 0x0020 with a value of 0x001. Thus, the ARCOUNT would appear to be 1 too. Why would DIG set this field to 1? What additional section might be in a request?
DIG bbc.co.uk
0x0000: 4500 0042 5164 0000 4011 d19e 0000 0000 [email protected]
0x0010: 0000 0000 b325 0035 002e 6e3f 266e 0120 .....%.5..n?&n..
0x0020: 0001 0000 0000 0001 0362 6263 0263 6f02 .........bbc.co.
0x0030: 756b 0000 0100 0100 0029 1000 0000 0000 uk.......)......
0x0040: 0000
I filled out the source and destination address in IP header with zeros.
That would be the OPT pseudo-RR for EDNS0. Back when it became clear that the original DNS standard was not quite enough, in order to not have to change any of the data format the choice was made to stick new headers fields and supplemental information in a special resource record in the Additional section. This is almost certainly what you're seeing.
See RFC 6891 for the details.