wiki:tcpeditDeveloper

Tcpedit Developer How To

TOC(depth=3)?

Please note that this document is a work in progress (ok, most of the pages on the wiki are a work in progress, but this one is more so). The good news is that as of 01/20/09 I have quite a few fully working plugins (three are both decoders and encoders), so hopefully this documentation is accurate. If you're interested in doing plugin development or you have any questions, please contact the tcpreplay-devel mailing list.

Note: This document really covers Tcpreplay up to 3.x. 4.0 will use a different build system (cmake instead of automake/autoconf) and a different header file organization. If you're interested in writing a plugin, please email the developer list and I'll be more then happy to help you out.

Overview

This is the libtcpedit plugin developer guide. I've tried to make it easy to extend libtcpedit by using plugins. There are plans for three types of plugins:

  1. DLT/Layer 2
  2. Layer 3 (IPv4, IPv6, etc)
  3. Layer 4-7 (Application)

Today, only the beginnings of the DLT/Layer 2 plugin infrastructure has been completed. Hence the purpose of this document is not only to teach people how to create a new plugin, but illicit feedback from people interested in writing plugins. Hopefully you'll let me know what you think of this API and if it will meet your needs in the future.

Conventions

Throughout this document I will use the format of <italics> to denote a variable you should supply. Variable names (between the < and >) will be consistent meaning that you should use the same value in various places. Constants will be in bold.

All plugins, are located in src/tcpedit/plugins off the root source code directory. Each plugin is stored in it's own directory. DLT/Layer2 plugins start with dlt_, Layer 3 plugins l3_ and Layer 4-7 plugins app_.

DLT Plugins

It hopes to provide you the basic information for creating a new DLT/Layer 2 plugin. DLT plugins allow you to:

  • Change the DLT type of the pcap file (converting from Linux_SLL or Cisco HDLC to Ethernet for example)
  • Change the values of Layer 2 fields (changing src/dst MAC addresses or altering VLAN tags, etc)

Generate New Plugin Template

Rather then starting from scratch, I've provided a simple way to start out with a template for your plugin. To create a copy of the template for your plugin, run the template script in the src/tcpedit/plugins directory:

./dlt_template.sh <name>

where <name> is the name of the dlt. Example for DLT_EN10MB (Ethernet), you would use en10mb. This will create a new directory called dlt_en10mb and populate it with 4 files (names will vary based on plugin name, but all the examples below are for en10mb):

  • The automake Makefile.am
  • A code and header file named after your plugin: en10mb.c & en10mb.h
  • A code and header file for your plugin's configuration API: en10mb_api.c & en10mb_api.h
  • The Autogen plugin option definition file: en10mb_opts.def

If you don't add any files, you won't have to modify the Makefile.am, otherwise you will have to make the appropriate changes.

After creating the new plugin template, you will need to add a single line to the src/tcpedit/plugins/Makefile.am so that it will include your plugin's Makefile.am:

include $(srcdir)/dlt_en10mb/Makefile.am

To get your plugin's options part of the tcpedit library, you will also need to add a line to the dlt_opts.stub file:

#include "dlt_en10mb/en10mb_opts.def"

If your plugin is an encoder with configuration options for the user to set, you should create a configuration API. This would be used in your plugin's *_parse_opts() function as well as other developers using libtcpedit. If you do this, be sure to add a line to the dlt_api.h file:

#include "dlt_en10mb/en10mb_api.h"

Update Build Environment

Then be sure to rerun ./autogen.sh and ./configure from the base tcpreplay source directory to update your Makefiles. Your new plugin will automatically get linked into libtcpedit.a.

Note: GNU make doesn't always seem to pickup changes to the plugin option definition file, so if you you may need to delete src/tcpedit/tcpedit_stub.h if this happens.

Register Your Plugin

The next step is to have your plugin register with the plugin base. To do so, edit src/tcpedit/plugins/dlt_plugins.c and:

  1. Add your plugin header file:
    #include "dlt_en10mb/en10mb.h"
    
  2. Find the function tcpedit_dlt_register in src/tcpedit/plugins/dlt_plugins.c. Call your registration function like this:
    retcode += dlt_en10mb_register(ctx);
    
    
  3. If your plugin supports output, edit src/tcpedit/plugins/dlt_opts.def and add your DLT type to the list:
    @item
    @var{enet} Ethernet aka DLT_EN10MB
    
  1. If your plugin supports input, edit src/tcprewrite_opts.def and add your DLT type to the list.

Starting To Code

In your new plugin directory, you'll find a file named <name>.c (eg. en10mb.c). You'll want to edit that and find near the top the section like:

/* edit these variables to taste */
static char dlt_name[] = "en10mb";
static char dlt_prefix[] = "???";
static u_int16_t dlt_value = 0xFFFF;

You will want to leave the value for dlt_name[] alone; this is the internal name of your dlt. dlt_prefix[] is the unique user visible name of your plugin and may or may not be different from the dlt_name. Generally speaking, I try to pick the "common name" like "enet" for ethernet since most people don't know it as en10mb. dlt_value is the numeric value of your DLT as defined by libpcap.

Important! The values of dlt_name[], dlt_prefix[] and dlt_value must be unique! Failure to use unique values will cause serious problems with the plugin system!

Below this, you will see each of the required functions already templated and ready to fill out. I've marked all the important sections which require work as FIXME: for easy searching.

You will also find <name>.h (eg. en10mb.h). This is your plugin header file. All the public functions are already prototyped here, as well as a structures to keep state and config information to be shared between function calls.

Option Parsing

The entire Tcpreplay suite uses GNU Autogen for option declaration and parsing. Autogen provides the AutoOpts automated option parsing which uses simple templates to define your options. Long story short, all your options need to start off with the value of dlt_prefix[]. So if your prefix is enet and you have source and destination addresses as well as options to process VLAN tags you would have:

  • --enet-src
  • --enet-dst
  • --enet-vlan-mode
  • --enet-vlan-tag
  • --enet-vlan-cfi

The important thing being that all the names of the options start with the value of dlt_prefix[]. For simplicity reasons, I strongly discourage using short (single character) options for plugins. While this creates additional typing, it is a lot clearer and AutoOpts has built in support for configuration files which reduce keystrokes.

The key thing here is put all the heavy lifting, sanity checks, etc in the *_api.[ch] files and use them in the *_parse_opts() function.

Developer Versions

These are the versions of various libraries/tools I have on my primary development box. I suggest you use the same versions to prevent incompatibilities.

  • GNU Autogen 5.9.7
  • GNU Automake 1.10.2
  • GNU Autoconf 2.63
  • libpcap 1.0.0
  • libdnet 1.11

Some important thoughts

  1. Not all plugins need a encode() and decode() function. One example might be for DLT_LINUX_SLL which uses a fake layer 2 header. In such cases, it make sense to decode these packets, but never to write them. Note, if you don't have an encoder function, not only can't you convert to but you can't write these packets at all (you will always have to select another DLT's encoder to write).
  2. It's important to fill out all the templated functions and to parse the given packet when applicable.
  3. Don't take shortcuts! For example, don't assume all ethernet packets have a header length of 14 bytes- 802.1Q vlan tagged frames will be 18 bytes.
  4. Options are there to modify the behavior of encoders and allow users to provide values for various fields. Do not use them for decoders.
  5. When reading the various Makefile.am's in src/tcpedit/plugin and it's subdirectories, remember that $(srcdir) == src/tcpedit
Last modified 8 years ago Last modified on 01/21/09 05:58:48