Back to Projects

Basic DNS Server

A quick pseudo DNS server written in C for the heck of it.

Introduction

I was thinking about web servers thanks to [CS280] Intro to Web Programming and I realized it wouldn't be too terrible to make. Now, this is not actually a DNS server since it does not use the DNS protocol, but it is a domain to IP lookup table basically.

Like any similar program, this is split into the server-side and the client-side. So naturally, we would have server.c and client.c. Of course, there are random helper and header files, but I will not cover those. You can view this project on my GitHub if you want to see the entire thing.

Again, this is not actually a DNS server since it does not use the same protocol but has similar behavior.

Client Behavior

When connecting to the server, the user will be presented with a little random messages. But most importantly, they will be able to enter commands. The client is equipped with the following commands:

get <domain> - This returns the IPv4 address (network order) of a given domain. As to how it gets this address will be explained in the next section. If the domain's address is cached, it will simply use that value.

put <domain:address> - This sends a request to the server and adds a domain-address pair to our DNS records. Keep in mind that the address must be an integer (which you can get via the get_addr.c script).

clearcache - Clears the cache. How the cache works will be explained next.

Caching

Right now, the cache is simply stored in cache.txt which just lists out each key-value pair separated by \n. When a get request is made, if it does not already exist in the file, its entry is added to the cache. Clearing the cache simply wipes the file clean.

Connectivity and Command Inputs

This was meant to be very bare bones and "use it if you know how to use it" project. Thus, if you try to connect to the server while it is down, it will seem normal (other than the fact you cannot run commands).

Also, for the most part, malformed inputs are treated as they would be regularly, so be careful about what you type. Basically the only thing that is checked is invalid addressed.

Server Behavior

The server is responsible for handling domain resolution and storage. It creates a TCP socket, binds to port 8080, and listens for incoming connections on all available interfaces. If initialization fails, the program terminates; otherwise, it continuously waits for clients. The core setup is:

int sock = socket(AF_INET, SOCK_STREAM, 0);
bind(sock, (struct sockaddr*) &server_addr, sizeof(server_addr));
listen(sock, CLIENT_BACKLOG);

Upon accepting a connection, the server enters a loop dedicated to that client. It reads incoming data, processes the request, and sends a response. If the client disconnects, it returns to waiting for new connections. This implementation is single-threaded, so clients are handled sequentially.

For a get request, it extracts the domain and looks it up in data.txt using a helper function. If the domain is not found, it returns an error message. Otherwise, the stored integer IP address is converted into dotted IPv4 notation and sent back to the client.

For a put request, the server appends the provided domain:address pair directly to data.txt. No validation or deduplication is performed. All records are stored in a plain text file, where each line represents a mapping. Lookups involve scanning the file, and writes append new entries.