CSCI 415/515: Fall 2022
Systems Programming
Project 5: adns

Due: Tue, Nov 15, 7:00am


In this project, you will implement a client (adns_lookup) and server (adns) which speak an "almost DNS" protocol. The Domain Name System, or DNS, is the "phone book of the Internet": whenever you browse to a URL (e.g., https://www.wm.edu/as/computerscience/resources/index.php) your browser must first lookup the IP address for the URL's domain name (e.g., www.wm.edu) so that it can make a connection to that site's webserver. The nitty-gritty details of the DNS protocol are specified in RFC 1034 and RFC 1035, but the gist is that the client sends the DNS server a domain name, and the server sends the client back the IP address, or an error indicating that the IP address can't be found. For our ADNS, we'll keep the spirit of this protocol, but implement a simpler on-the-wire protocol than what is specified in the RFCs. The real DNS can use either UDP or TCP, and likewise our ADNS client and server will support both transport protocols.

Protocol

In our ADNS protocol, every message (request and response) has the same format:

     id     
u32be
 type 
u16be
body_len
u16be
 body 
u8[]

In particular, each message has an 8-byte header consisting of an id, a type, and a body_len, all of which are big-endian. After the header, a message has a body that is body_len bytes long.

id

The id is randomly chosen by the client for its request message (for this project, you can simply hardcode a value). When responding to a request, the server sets the response's id to that of the request's.

type

The message type. For requests, there is only one type:

QTYPE_A (1)
Lookup the IPv4 address for a domain name. The request's body contains the domain name. Note that the domain name does not have a trailing nul-byte. For this type of message, body cannot be zero-length.

Responses can have one of the following types;

RCODE_NOERROR (0)
The server successfully looked up the requested value. The response's body contains the value. Note that the value does not have a trailing nul-byte.
RCODE_FORMERR (1)
The client's request was malformed. This message has a zero-length body.
RCODE_NXDOMAIN (3)
The server could not resolve the request. This message has a zero-length body.
body_len
Even though body_len is a 16-bit value, we will impose that the maximum value for body_len is 253 bytes.

adns_lookup


Name

adns_lookup - Make a lookup request to an adns server.

Synopsis

adns_lookup [-h] [-p PORT] [-t] HOST QUERY

Positional Arguments

HOST

The IPv4 address of the ADNS server (e.g., 127.0.0.1).

QUERY

The domain name to resolve (e.g., leo).

Options

-h, --help

Print a usage statement to stdout and exit with status 0.

-p, --port PORT

The ADNS server's port. (default: 9514)

-t, --tcp

Use TCP instead of UDP.

Exit Status

If the name was resolved, then adns_lookup has an exit status of zero, otherwise the program has a non-zero exit status.

adns


Name

adns - A simplified version of a DNS server for IPv4.

Synopsis

adns [-h] [-i IP_ADDRESS] [-p PORT] [-t] ZONE_FILE

Positional Arguments

ZONE_FILE

File that maps domain names to IPv4 addresses. Each line of the file contains two fields -- (1) the domain name and (2) the IPv4 dotted-decimal address -- separated by one or more spaces.

Options

-h, --help

Print a usage statement to stdout and exit with status 0.

-i, --interface IP_ADDRESS

The interface to listen on. (default: INADDR_ANY)

-p, --port PORT

The port to listen on. (default: 9514)

-t, --tcp

Use TCP instead of UDP.

Skeleton Code

To help get started, please use the following skeleton code for the server (though common.h, mu.h, and mu.c will also be useful for the client):

If you're working from a Linux terminal, it's easy to download these files using the curl tool:


      curl -O https://www.cs.wm.edu/~smherwig/courses/csci415-f2022/adns/src/adns.c
      curl -O https://www.cs.wm.edu/~smherwig/courses/csci415-f2022/adns/src/common.h
      curl -O https://www.cs.wm.edu/~smherwig/courses/csci415-f2022/adns/src/mu.c
      curl -O https://www.cs.wm.edu/~smherwig/courses/csci415-f2022/adns/src/mu.h
      curl -O https://www.cs.wm.edu/~smherwig/courses/csci415-f2022/adns/src/uthash.h
      curl -O https://www.cs.wm.edu/~smherwig/courses/csci415-f2022/adns/src/Makefile
      

The skeleton code currently implements the getopt_long option parsing, reads in the zone file, and then prints the zone file.

adns.c reads the zone file into a hash table. For this data structure, we use uthash -- a popular hash table implementation. Since the skeleton code already initializes this hash table, there is very little that you have to with respect to uthash. The function zone_get_rr in adns.c is a wrapper for looking up a value in the hash table. If you are attempting bonus1, you will want to consult the uthash user guide to learn how to iterate over the hash table.

Python versions of client and server

To help you develop the projects, you can use the following Python versions of the client and server:

The Python implementations have the same command-line usage as the C-versions that you will implement. Many of the automated tests will use these scripts to separately test your client and your server.

Note that after you download these scripts, you should make them executable:


      chmod +x adns_lookup.py adns.py
      

Bonus 1: Reverse Lookup

Implement the QTYPE_PTR (12) message type: the request's body is a domain name, and the the response's body is the dotted-decimal IP address. In other words, QTYPE_PTR signifies a reverse lookup. If the server cannot resolve the lookup, it should return NXDOMAIN (and a zero-length body).

The command-line usage of the adns does not change. For adns_lookup, a short option of -r or a long option of --reverse indicates a reverse lookup.

Bonus 2: TXT Lookup

Implement the QTYPE_TXT (16) message type: the request's body is an arbitrary key, and the the response's body is associated value. Normal DNS uses TXT resource records as a generic "catch-all" for data that doesn't match any existing record type. Our ADNS server will only implement one key: "version", and should respond with "adns v1.0". If the ADNS server receives any other key, it should respond with NXDOMAIN (and a zero-length body).

The command-line usage of the adns does not change. For adns_lookup, a short option of -x or a long option of --txt indicates a reverse lookup.

Submitting

Submit your project as a zip file via gradescope. Your project must include a Makefile that builds two executables: adns_lookup and adns. Please refer to the instructions for submitting an assignment for details on how to login to gradescope and properly zip your project.

Rubric

Note: All of the output for the tests below is to stdout.

Input Files

zone.conf


      

Server UDP


1.1 NOERROR (7 pts)


          ./adns zone.conf
          

          ./adns_lookup.py 127.0.0.1 leo
          1.2.3.5
          

1.2 NXDOMAIN (7 pts)


          ./adns zone.conf
          

          ./adns_lookup.py 127.0.0.1 tiger
          not found
          

1.3 FORMERR (7 pts)


          ./adns zone.conf
          

          ./adns_lookup.py 127.0.0.1 ''
          malformed request
          

Server TCP


2.1 NOERROR (7 pts)


          ./adns -t zone.conf
          

          ./adns_lookup.py -t 127.0.0.1 pisces
          1.2.3.12
          

2.2 NXDOMAIN (7 pts)


          ./adns -t zone.conf
          

          ./adns_lookup.py -t 127.0.0.1 pig
          not found
          

2.3 FORMERR (7 pts)


          ./adns -t zone.conf
          

          ./adns_lookup.py -t 127.0.0.1 ''
          malformed request
          

Client UDP


3.1 NOERROR (7 pts)


          ./adns.py zone.conf
          

          ./adns_lookup 127.0.0.1 libra
          1.2.3.7
          

3.2 NOERROR zero exit status(4 pts)


          ./adns.py zone.conf
          

          ./adns_lookup 127.0.0.1 libra
          1.2.3.7
          echo $?
          0
          

3.3 NXDOMAIN (7 pts)


          ./adns.py zone.conf
          

          ./adns_lookup.py 127.0.0.1 horse
          not found
          

3.4 FORMERR (7 pts)


          ./adns.py zone.conf
          

          ./adns_lookup.py 127.0.0.1 ''
          malformed request
          

Client TCP


4.1 NOERROR (7 pts)


          ./adns.py -t zone.conf
          

          ./adns_lookup -t 127.0.0.1 gemini
          1.2.3.3
          

4.2 NXDOMAIN (7 pts)


          ./adns.py -t zone.conf
          

          ./adns_lookup.py -t 127.0.0.1 rabbit
          not found
          

4.3 NXDOMAIN non-zero exit status(4 pts)


          ./adns.py -t zone.conf
          

          ./adns_lookup.py -t 127.0.0.1 rabbit
          not found
          echo $?
          1 # or any non-zero value
          

4.4 FORMERR (7 pts)


          ./adns.py -t zone.conf
          

          ./adns_lookup.py -t 127.0.0.1 ''
          malformed request
          

Alternate Port


5.1Server UDP (5 pts)


          ./adns -p 9553 zone.conf
          

          ./adns_lookup.py -p 9553 127.0.0.1 leo
          1.2.3.5
          

5.2Client TCP (7 pts)


          ./adns.py -t --port 9553 zone.conf
          

          ./adns_lookup -t --port 9553 127.0.0.1 aquarius
          1.2.3.11
          

Bonus 1: Reverse Lookup


100.1Server UDP (4 pts)


          ./adns zone.conf
          

          ./adns_lookup.py -r 127.0.0.1 1.2.3.5
          leo
          

100.2Client TCP (4 pts)


          ./adns.py -t zone.conf
          

          ./adns_lookup -t -r 127.0.0.1 1.2.3.8
          scorpio
          

100.3Server NXDOMAIN (2 pts)


          ./adns zone.conf
          

          ./adns_lookup.py -r 127.0.0.1 4.5.6.7
          not found
          

Bonus 2: TXT Lookup


200.1Server UDP (4 pts)


          ./adns zone.conf
          

          ./adns_lookup.py -x 127.0.0.1 version
          adns v1.0
          

100.2Client TCP (4 pts)


          ./adns.py -t zone.conf
          

          ./adns_lookup -t -x 127.0.0.1 version
          adns v1.0
          

100.3Server NXDOMAIN (2 pts)


          ./adns zone.conf
          

          ./adns_lookup.py -x 127.0.0.1 foo
          not found