mydump is a simple C project that parses packets using libpcap. It can either read a pcap file or capture live on an interface.

Most of the parsing is done by just casting raw pointers into structs. The parsers are called recursively: an ethernet packet encapsulated in a layer 4 one (VXLAN for example) will be correctly parsed.

This architecture, combined with a few macros, has let me define new protocols quite rapidly. Here's the full implementation of the VXLAN decoding:

#define vni vni_reserved >> 4
struct vxlan_hdr {
  u_int16_t flags;
  u_int16_t group_policy;
  u_int32_t vni_reserved;
};

static void handle_vxlan(uint32_t length, const uint8_t* packet) {
  struct vxlan_hdr *vxlan = (struct vxlan_hdr *)packet;
  APPLY_OVERHEAD(struct vxlan_hdr, length, packet);
  DEBUGF("VXLAN vni: 0x%06x", vxlan->vni);
  indent_log();
  handle_ethernet(length, packet);
  dedent_log();
}

A few things interesting things in this project:

The list of handlers for a specific layer is stored in a static array of functions, with the port/protocol number as index. C99 has Designated initializers that allows to specify those indexes. The array will then take the last index as size and fill missing items with zeros. With this trick, looking up a handler is a O(1) operation.

typedef void(*udp_handler)(uint32_t, const uint8_t*);

static udp_handler handlers[] = {
  [53] = handle_dns,
  [67] = handle_bootp,
  [68] = handle_bootp,
  [4789] = handle_vxlan,
};

udp_handler resolve_udp_handler(const uint16_t port) {
  if (port >= (sizeof(handlers) / sizeof(udp_handler)))
    return NULL;
  return handlers[port];
}

I also did a few fun things with logging using macros. If you take a look at util.h, you'll find logging macros where most of the work is done at compile time. Log messages include the log level and the location of the call (file & line number) with fancy ANSI colors.

The log level can either be defined at runtime or at compile time. Because there's really no function call, if the log level is set at compile time, unused log messages are completely stripped out of the binary.