CS 43 Lab 3: Talking to DNS

Due: Thursday, October 12, 11:59 PM


Handy references:


Lab Audio, day 1

Overview:

For this lab, you'll be implementing the DNS protocol to build your very own iterative name resolver.

Your server program will receive one optional flag (-m) and one argument: the host name we'd like to resolve. If the flag is absent, you're being asked to resolve a host name's IP address. If the flag is present, you're being asked to find the mail exchange for a domain. For example:

$ ./lab3 celery.cs.swarthmore.edu
(...progress output...)
The name celery.cs.swarthmore.edu resolves to: 130.58.68.156
$ ./lab3 -m cs.swarthmore.edu
(...progress output...)
The mail exchange for cs.swarthmore.edu resolves to: 130.58.68.9

Note: you should also be able to look up the mail server that a machine should use, e.g.,

$ ./lab3 -m sesame.cs.swarthmore.edu
(...progress output...)
The mail exchange for cs.swarthmore.edu resolves to: 130.58.68.9

Here, you'll get an MX answer telling you that cs.swarthmore.edu is the name of the mail server. You'll then need to do an additional query to resolve its name to an A record of 130.58.68.9.

You should assume that there will be a file named root-servers.txt in your program's current working directory and that it contains a list of IP addresses for root DNS servers. Your program must use this file to find a root server. It should iteratively work its way down the DNS hierarchy, querying the root, then the TLD, then authoritative server(s) until resolves the requested host name.

Requirements

  1. You may use any programming language you want for this lab. I encourage you to try Python so that you can see the similarities and differences between high- and low-level languages with respect to network programming. Regardless of which language you choose, you must NOT use any libraries that simplify DNS or hide the details of socket programming! Don't make any calls to gethostbyname()/getaddrinfo() or the equivalent functions in the language you choose. If you have any doubt about which functions you may use, please ask!

  2. If you attempt to query a server and get no response after waiting a short time (approximately 5 seconds), your program should move on to the next server and attempt to query that instead.

  3. Your program should query for host name to IP address mappings (Type A, decimal value 1) unless given the -m flag, in which case it should query for mail exchanges (Type MX, decimal value 15).

  4. Your program should print short status messages regarding its intermediate steps as it traverses the DNS hierarchy. For each request you make, you should output the server you're querying and a brief summary of the response you got back. If you didn't get a response (because you timed out), say so. You should print:
    1. When you're about to make a query, tell me who you're querying (IP address is fine, name + IP is nice if you have that info available.
    2. Tell me the result of the query (success, failure, timeout, etc.).
    3. If it was successful and it was the final query, print the final result. Otherwise, continue querying.
    This info will allow me to trace your code's path down the DNS hierarchy.

  5. If asked to resolve an invalid name, your program should print an error message.

  6. You should never ask a DNS server to perform a recursive query for you.

You may assume that the additional records section will contain the A records for any server names listed in the NS records of the authority record section.

High-level checklist

Roughly, your server should follow this sequence:

  1. Check the arguments to determine if it's being invoked for an A or MX lookup.
  2. Populate a collection of root DNS server IP addresses from root-servers.txt.
  3. Create a UDP socket and craft a query.
  4. Send that query to a root server and wait for a response. If you wait too long, move to the next root.
  5. Continue this process as you work your way down the hierarchy, only instead of using the root servers for subsequent queries, use the NS record results from previous query's response.
  6. Once you've made it down to the final authoritative server, inform the user of the result and exit.
  7. You may find that structuring your program with recursion is helpful. For example, in processing one lookup, you might need to start another. If your code can call itself again, it'll be easier!

If you have any questions about the lab requirements or specification, please post on Piazza.

Grading Rubric

This assignment is worth five points.

When submitting, please provide a small executable script named "lab3" along with your program. This script should take the same arguments as your program (described above) and it should call your program with those arguments. This helps me to account for various ways of invoking programs in different languages when grading your assignments.

Tips

Submitting

Please remove any debugging output prior to submitting.

To submit your code, simply commit your changes locally using git add and git commit. Then run git push while in your lab directory.