Using libnetdude

`libnetdude` Manual
Prev |  | Next

# Using `libnetdude`

This chapter explains how to build `libnetdude`, what parts of `libnetdude` end up where on your system when you install it, and how to build other programs that use `libnetdude`.

# Building `libnetdude`

Building `libnetdude` will hopefully be easy. `libnetdude` has two dependencies, make sure these are installed before you try to build your copy:

- glib, version 1.2.10 or higher. Download it from gtk.org or just grab an RPM/DEB for it. Do not forget the development packages if your distibution uses those, since you will need the header files during the build process.

- libpcapnav, downloadable from netdude.sf.net.

The build itself is made using the common ./configure && make && make install sequence. Check ./configure --help for a list of available options, particularly the --with-pcapnav... options to specify a `libpcapnav` that's installed in an unusual location.

# Installation Layout

The installation places files in the following locations (the full path depends on what --prefix option you passed to configure. The default value is `/usr/local`):

- `$prefix/lib/`: the core library, in static and dynamic linking versions (unless disabled at configuration time).

- `$prefix/include/libnetdude/VERSION`: header files of the core library.

- `$prefix/include/libnetdude/VERSION/protocols`: header files of protocol plugins that are part of the core distribution.

- `$prefix/include/libnetdude/VERSION/plugins`: header files of feature plugins that are part of the core distribution.

- `$prefix/share/libnetdude/VERSION/protocols`: DLLs of protocol plugins that are part of the core distribution.

- `$prefix/share/libnetdude/VERSION/plugins`: DLLs of feature plugins that are part of the core distribution.

- `$prefix/bin`: the lndtool program.

# The lndtool Program

`libnetdude` comes with a tool for querying the local `libnetdude` installation: lndtool. Have a look at its command line options:

    lndtool -- libnetdude configuration and execution tool.
    USAGE: lndtool [OPTIONS]

      --help, -help, -h, -?        This message.
      --prefix                     Installation prefix.
      --version, -v                Prints out version info.
      --cflags                     Preprocessor flags needed for compilation.
      --libs                       Linker flags needed when linking..
      --plugin-dir                 Plugin installation directory.
      --proto-dir                  Protocol installation directory.
      --include-dir                Header files directory.
      --plugins                    Lists all plugins that register successfully.
      --run, -r PLUGINNAME PARAMS  Run plugin PLUGINNAME with PARAMS.

As you can see, most of the options look familiar from package configuration scripts normally called <package>-config. `libnetdude` uses a separate program (and it is a binary executale, not a shell script) because in the case of `libnetdude` you may want to query settings that require `libnetdude` to be loaded and initialized, such as listing the installed plugins. lndtool behaves just like a libnetdude-config would, but has two additional features:

- --plugins: this option lists all the plugins currently installed that register themselves successfully.

- --run,-r PLUGINNAME [PARAMS]: this options allows you to run the feature plugin PLUGINNAME directly from the command line. Additional parameters are wrapped in a LND_PluginArgs structure and passed to the plugin. This shortcut significantly increases code modularity for reasons explained in the next section.

  | Plugin name lookups are case-insensitive.

# Building Applications with `libnetdude`

In this section, we'll first look at how you can check for `libnetdude` in autoconf scripts. Then we get a bit technical and explain how linking to the library and its plugins works.

## Handy autoconf Code

If you are using the autoconf/automake tools to configure your package, use the following check to detect `libnetdude`:

    dnl ##################################################
    dnl # Check for libnetdude
    dnl ##################################################
    AC_ARG_WITH(lndtool,
        AC_HELP_STRING([--with-lndtool=FILE], [Use given lndtool]),
        [ lndtool="$withval" ],
        [ AC_PATH_PROG(lndtool, lndtool,
                       AC_MSG_ERROR(Cannot find lndtool: is it in path?)) ])

    LIBNETDUDE_CFLAGS=`$lndtool --cflags`
    LIBNETDUDE_LIBS=`$lndtool --libs`
    AC_SUBST(LIBNETDUDE_LIBS)
    AC_SUBST(LIBNETDUDE_CFLAGS)
    # same for any other options you require ...

You can then use the compiler/linker flags that `libnetdude` requires in your `Makefile.am` using `@LIBNETDUDE_CFLAGS@` and `@LIBNETDUDE_LIBS@`.

| Using the output of `lndtool --cflags|--libs` provides all the compiler/linker flags you need to pull in the dependencies (`libpcapnav` and glib). You do not need to add extra checks and flags for those dependancies in your build scripts.

## Linking with `libnetdude` and its Plugins

Let's assume you are writing a program that uses `libnetdude` and you want to link your compiled object files with `libnetdude` (we assume shared libraries here). If your program uses only symbols (functions, globals, etc) from `libnetdude` itself, this is not a problem: you simply use the linker flags provided by lndtool --libs. However, if you are using symbols from plugins, things are more tricky. Say we have a plugin called Boofar that defines functions `libnd_boofar_foo(LND_Trace *)` and `libnd_boofar_bar(LND_Trace *)` in a header file called `libnd_boofar.h`. Consider the following code that opens a trace file passed on the command line (without error checking, shame on them), and then passes the opened trace to these two functions before closing the trace.

    #include <libnd.h>
    #include <plugins/libnd_boofar.h>

    int
    main(int argc, char **argv)
    {
      LND_Trace *trace;

      libnd_init();

      trace = libnd_trace_new(argv[0]);
      libnd_boofar_foo(trace);
      libnd_boofar_bar(trace);
      libnd_trace_free(trace);

      return 0;
    }

At build time, the necessary declarations are taken from the plugin's header files (found because we pass the output of lndtool --cflags to the compiler), so the compilation completes fine. However, when you try linking your program, you will get something like this:

    /tmp/ccnIJufv.o(.text+0xa6): In function `main':
    : undefined reference to `libnd_boofar_foo'
    /tmp/ccnIJufv.o(.text+0xc0): In function `main':
    : undefined reference to `libnd_boofar_foo'

The problem is that the Boofar plugin is loaded dynamically when `libnetdude` bootstraps, hence the plugin's symbols are not found when linking. There are two possible solutions to this problem:

- Pass the plugin's shared object file when linking. This is ugly for a number of reasons. You need to know the names of Boofar's binary files. You need to make sure that your executable will find them when it starts (likely using --rpath magic). Passing the plugin binaries to the linker does not make sense, since `libnetdude` will dynamically link in the plugins when initialized. Worst of all, you also need to pass the binary files of any other plugins that Boofar requires.

  In the end this approach boils down to passing all installed plugin binaries to the linker, defeating the intention of the plugins. This approach therefore is not acceptable.

- Do not link your code into a standalone executable. This sounds odd, but when you link the code into a shared executable, the linker will not complain about unresolved symbols and defer the linking until runtime. In short, your program becomes another plugin, which is exactly the purpose of `libnetdude`'s modular design. To run your program, you then use a wrapper program that calls your plugin on your behalf. Remember lndtool --run, described in the previous section? Now you know its purpose.

Let's see how this works. We change the code to have a minimalistic but valid `libnetdude` feature plugin structure:

    #include <libnd.h>
    #include <plugins/libnd_boofar.h>

    const char *
    name(void)
    {
      return "Boofar-App";
    }

    gboolean
    run(LND_Trace *unused, LND_PluginArgs *args)
    {
      LND_Trace *trace;

      printf("Opening trace file %s.\n", trace->filename);
      trace = libnd_trace_new(args->argv[0]);
      libnd_boofar_foo(trace);
      libnd_boofar_bar(trace);
      libnd_trace_free(trace);

      return TRUE;
    }

Now you compile and link this code as a `libnetdude` plugin, for example using the code template provided on the SourceForge site. Otherwise there is no difference: your build environment will have to check for `libnetdude` anyway. The linker does not find the Boofar symbols, but this time it does not complain. After installing the plugin, you can then run your app using lndtool like this:

    lndtool --run Boofar-App mytracefile.trace
    Opening trace file mytracefile.trace.

If you find this too cumbersome, wrap the call in a shell script as often done with Java applications and there's no visible difference.

# `libnetdude`'s Testsuite

Should you decide to delve into hacking `libnetdude` itself (yay!), you'll want to have a look at the contents of the `test` directory in the source tree. It contains a few programs that can be built using make tests and that are not installed. These programs are:

- `lnd-test`: a test driver that consists of a set of functions that exercise several aspects of the library, primarily trace part management and trace navigation. More tests are highly welcomed contributions, and may make the authors more apt to supporting extensions of the library using the bribery method explained in the chapter on `libnetdude` Plugins.

- `lnd-test-filter`: a small demo/test program that shows how to use the `libnetdude` filter API.

- `lnd-test-plugins`: a helper app that prints the names, versions, and authors of the installed feature and protocol plugins to the console.

- `lnd-dump`: a helper app gives you the equivalent of running tcpdump on a trace file, printing out the familiar ouput for each packet. Additionally, you get the offset of the packets (absolutely and relatively to the end of the pcap savefile header) prepended to the line. Have a look at `lnd-dump.c` and see how easy the code is.

Prev | Home | Next
`libnetdude` Concepts |  | `libnetdude` Plugins