Simple Packet Sniffer in C

As my final project for my Computer Networks subject at ESCOM I wrote a simple packet sniffer in C, it was a fun little project and this is my documentation about it.

Hello! This is a translation from an old post (2019) I wrote in spanish (that you can find here, in my school subject repository) and it includes a detailed description on the rationale behind its design, implementation and usage. If you’d like to get the source code you can visit the github repository at github.com/humbertowoody/redes-escom/Proyecto-Final.

Building a Simple Network Packet Sniffer

“There was a time when people felt the internet was another world, but now people realize it’s a tool we use in this world”.

  • Tim Berners Lee.

As my final project for my Computer Networks subject at ESCOM, I decided to implement a network packet sniffer that allows capturing, analyzing, and exporting data quickly and easily. The program is written in C/C++ using the libpcap library for analysis and data export functionalities.

Table of Contents

Objectives

There are many network packet capturing (and interpreting) software applications available, each with various features depending on the intended use case. This project aims to cover only basic functionalities, providing a sort of guide for developing more complex programs requiring similar features. The functionalities considered include:

Implementation

To develop this program, we started by analyzing the user flow while interacting with the software, focusing on simplicity and efficiency.

First, the program prints a welcome header and follows this flow:

  1. Ask the user if they want to capture packets on the fly or from a file.
  2. On the Fly
    1. Display a list of available network cards.
    2. User selects a network card.
    3. Ask the user for the maximum packet size; the recommended value is 65536.
    4. Ask the user if the interface should operate in promiscuous mode.
    5. Ask the user for the timeout for packet capture; the recommended value is 1000 (in ms).
    6. Ask the user if they want to save captured packets in a file.
    7. Save
      1. Ask for the filename.
      2. Open the file.
  3. From a File
    1. Ask the user for the filename to read packets.
  4. Ask the user for the number of packets to capture.
  5. Ask the user if they want to use a capture filter.
  6. With Filter
    1. Ask the user for the filter.
    2. Compile the filter.
    3. Apply the filter.
  7. Analyze packets.
    1. Receive the packet.
    2. Print capture date.
    3. Analyze Ethernet/802.3.
    4. Analyze IP.
    5. Analyze ICMP, TCP, or UDP.

The source code closely follows this flow and is how the compiled program operates.

Testing

To test the program correctly, we need to consider all valid use cases. Instead of listing hundreds of tests, we’ll focus on the crucial use cases for our Sniffer:

Capturing Packets on the Fly

To capture packets on the fly, select the first option in the main menu. Then, fill in the configuration, and the program will produce an output similar to:

Hey there! So, the output was just too long to fit nicely in this blog post. No worries though - I’ve moved it to this GitHub gist for you to check out whenever you like. Enjoy!

This output confirms that the capture was performed correctly using the specified network card.

Capturing Packets from a File

To test the program by reading packets directly from a file, select the second option in the main application menu. Fill in the filename, specify the number of packets, and choose whether to apply a capture filter. The output will be similar to:

Hey there! So, the output was just too long to fit nicely in this blog post. No worries though - I’ve moved it to this GitHub gist for you to check out whenever you like. Enjoy!

This output verifies that our program can analyze packets contained in a standard packet capture format file (.pcap).

The packets I used for this demo are in the paquetes.pcap file, which is specific for testing packet analysis with an Ethernet 802.3 header, but it works with any type of packets. Please visit the GitHub repository if you’d like to see the file.

Applying Capture Filters

It’s essential for our program to apply capture filters, allowing the user to make better use of our Sniffer. We can use capture filters with either on-the-fly or file-based captures, and the filter should have specific syntax. Suppose we want to capture only all DNS traffic, which is UDP using port 53. In that case, our program will display output like:

Hey there! So, the output was just too long to fit nicely in this blog post. No worries though - I’ve moved it to this GitHub gist for you to check out whenever you like. Enjoy!

This output proves that the program can successfully specify and apply capture filters.

Exporting Capture to a .pcap File

Exporting our capture to a standard format file (like .pcap) allows us, as users, to capture packets and analyze them using specialized analysis software like WireShark for more detailed analysis with more comprehensive (and complex) tools.

To test this option, select the on-the-fly packet capture and choose to export the capture to a file when prompted. Specify the filename to store the capture rate. Suppose we want to capture all ICMP packets and export them to an icmp.pcap file for further analysis with WireShark. In that case, the program execution with those steps in mind will display:

Hey there! So, the output was just too long to fit nicely in this blog post. No worries though - I’ve moved it to this GitHub gist for you to check out whenever you like. Enjoy!

This successful test allows us to perform more detailed analysis of raw packets in compatible software like WireShark.

Conclusion

Developing such a simple tool requires a general understanding of networking concepts to break down the captured data into different interpretations useful for the user. Although many packet capture programs currently exist, developing a Sniffer helps us better understand our network’s behavior and the packets that flow through it.


Message from 2023

This was a fun project to write and even it’s code can be improved, the overall networking concepts surrounding the internals of a packet sniffer remain as current as ever.

Thanks for taking the time to read this!