Success I have finally managed to get the whole IP stack working. As an added bonus DNS is also working. To begin with I will discuss how DNS ended up working. DNS works by sending a message to a DNS server with a correctly formatted website query. In reply we receive the website server IP address. Messages are sent by UDP. UDP has the following layout.

typedef struct
{
  IPhdr ip;
  unsigned int sourcePort;
  unsigned int destPort;
  unsigned int len;
  unsigned int chksum;
}UDPhdr;

Now the source port in this will be anything past 50000 as it ultimately doesn’t matter. The destination  has to be 53 as that is what is used for DNS. The length is of course the length of our data after the IP header. The check sum is a bit annoying for UDP it is the destination and source IP address plus IP protocol plus length of data. This is then added onto the checksum of the rest of the data after the IP header. Sound confusing well it was the cause of many problems. The DNS header is as follows.

typedef struct
{
  UDPhdr udp;
  unsigned int id;
  unsigned int flags;
  unsigned int qdCount;
  unsigned int anCount;
  unsigned int nsCount;
  unsigned int arCount;
}DNShdr;

Now the id can be anything as it used to identify our query when it returns. Flags consist of a 16 bit field of flags: QR Opcode AA TC RD RA Z AD CD Rcode. QR is query or response since this is a query we leave that as zero. Opcode is zero for a query. The rest of the fields aren’t needed as they are all for extra parts of DNS. Rcode is the return code or error message. It should probably be checked on return. qdCount is the number of questions we only need to ask one so this is set to one. an ns and ar count are all set to zero as they are not required.

After the DNS header is the DNS query this consists of an encoded string. The encoding is the length of the string until the next period followed by the data. For example “www.google.co.uk” would be “3www6google2co2uk0”. After the query is two two byte fields. The first field is type this is 1 for an IPV4 address. The second field is class for internet this is 1 as well. So after doing all of that we can combine all of information together and send it off.

When we receive our reply there will be a lot of other data in it. But luckily the return data is always at the end of the packet. So we can just take the last 4 bytes of data after confirming that this is the correct packet according to ID number and error code.

We now have a working DNS lookup the next post will be about how to apply all of this so that TCP can be used to send a HTTP message.

Advertisements