-
Introduction
Libnet is a reasonably small programming library, written mainly in C, providing a high-level, standard portable interface to low-level network packet shaping, handling and injection primitives. To further understand this rather wordy definition, let's go through it and expand on the major points.
- high-level interface: Libnet is written mostly in C and was designed to abstract out the pedantic architecture-specific details of low-level packet shifting.
- low-level packet shaping: One of libnet's major value-adds is the complete control it offers over every packet header field.
- portable interface: Libnet's interface is standard whether you're working on Linux, FreeBSD, Solaris or Windows NT.
- packet shaping: Libnet offers a wide array of packet constructors for several protocols (inside of TCP/IP).
- packet handling: Libnet also has a suite of supplementary functions to automate many of the tedious tasks inherent in low-level network programming.
- packet injection: Libnet allows the user to choose between two different packet injection methods.
Libnet was developed for two major reasons:
- To establish a simple interface by which network programmers could ignore the subtleties and nuances of low-level network programming (and therefore concentrate on writing their programs and solving their problems).
- To mitigate the irritation many network programmers experienced due to the lack of standards.
Prior to libnet, programmers had to struggle with confusing, obscure, and poorly documented interfaces to construct and write network packets. Libnet alleviates these problems and provides a well documented, simple API to quickly build portable programs that write network packets.
This short tutorial is designed to be an overall introduction to libnet and it will describe the library in moderate detail. This includes internals, design decisions and futures, as well as a step by step coding example.
-
Why use Libnet?
Libnet is a very robust enabler in building useful and complex network applications (in fact, in June of 2000, a survey of 1200 nmap users found libnet and several libnet-based applications to be among their top 5 favorite security tools).
While some people may see libnet as a tool for hackers because it can be used to quickly craft network-based exploits, this is a very myopic point of view. Libnet can be used (and indeed has been used) to build vastly powerful network and network security based applications. It allows the implementor absolute control of packets on a discrete level, something not offered by traditional network programming interfaces. This control combined with libnet's easy to use interface make it a very effectual value-add to any network programmer.
-
Library Overview
Libnet is a simple C library. It is designed to be small, efficient and easy to use. Libnet's main goal is portable packet creation and injection. As of version 1.0.2, the core libnet tree consists of about 8000 lines of code in 43 files. There are 63 user-accessible functions, 26 of which are packet constructor routines. Libnet currently has support for 10 protocols with several in development.
Figure 1. Libnet Supported Protocols

Architectural Support
Libnet has been ported to several of today's popular architectures. The following is a list of confirmed ports.
- OpenBSD 2.2 - 2.7 (i386)
- FreeBSD 2.2 - 4.0 (i386)
- NetBSD 1.3.x (i386)
- BSD/OS 3.x (i386)
- BSDi 3.0 (i386)
- Linux 2.2.x, 2.0.3x, 2.1.124 (i386, alpha) (libc: 2.4.x, glibc: 2.0.x)
- Solaris 7 (SPARC, gcc 2.7.2[13], 2.8.2), 2.6 (SPARC, gcc 2.8.2), 2.5.x (SPARC, gcc 2.7.2[13])
- IRIX 6.x
- MacOS 5.3rhapsody (powerpc)
- Windows NT 4.0 and 5.0 (i386)
Getting Started
To continue with this tutorial the programmer should download and install the library (version 1.0.2 is recommended): http://www.packetfactory.net/libnet/libnet.tar.gz. Even if your operating system includes libnet (many open-sourced OSs do), you might want to check and make sure you have a recent version of libnet:
strings $PATH_TO_LIBNET/libnet.a | grep version
If you've got 1.0.x, you're good to go.
Libnet uses GNU autoconf for precompilation configuration, so to start it on its way, simply type:
./configure.
Then to build and install the library:
make; make install
And optionally to build the test and example modules:
make test; make example
Libpcap
It is recommended that the programmer also install libpcap from http://www.tcpdump.org (it will be required for the coding example below). Incredibly useful and powerful programs can be written with libnet in conjunction with libpcap.
Figure 2. Application layering with libnet and libpcap

Now you're ready to start writing code.
-
Design Decisions
Modularity
Big programs are made up of many smaller modules [1]. These modules provide the user with functions and data structures that are to be used in a program. A module comes in two parts: its interface and its implementation. The interface specifies what a module does, while the implementation specifies how the module does it. The interface declares all of the data types, function prototypes, global information, macros, or whatever is required by the module. The implementation adheres to the specifications set forth by the interface. Libnet is designed off of this paradigm. Each implementation, you'll find, has a corresponding interface.
Figure 2. Interfaces and Implementations

There is a third piece to this architecture: the client. The client piece is code that imports and employs the interface, without having to even see the implementation. The programs developed on top of libnet are `client` code.
The configure script
Early on in the development of libnet, it became clear that there was a great deal of OS and architecture dependent code that had to conditionally included and compiled. The autoconf configuration stuff (circa version 0.7) worked great to determine what needed to be included and excluded in order to build the library, but did nothing for post-install support. Many of these CPP macros were needed to conditionally include header information for user-based code. This was initially handled by relying on the user to define the proper macros, but this quickly proved inefficient.
Libnet now employs a simple configure script. This script is created during the autoconf configuration and is installed when the library is installed. It handles all of the OS and architecture dependencies automatically. It is mandatory to use the script. You will not be able to compile libnet-based code without it. The script is very simple to use. The following examples should dispel any confusion:
At the command line you can run the script to see what defines are used for that system:
echelon:~> libnet-config --defines
-D_BSD_SOURCE -D__BSD_SOURCE -D__FAVOR_BSD -DHAVE_NET_ETHERNET_H -DLIBNET_LIL_ENDIAN
At the command line to compile a simple program:
echelon:~> gcc -Wall `libnet-config --defines` foo.c -o foo `libnet-config --libs`
In a Makefile:
DEFINES = `libnet-config --defines`
In a Makefile.in (employing autoheader):
DEFINES = `libnet-config --defines` @DEFS@
Injection Methods
Libnet offers two interfaces to inject packets on to the network; the raw socket interface and link-layer interface. People often wonder when to use the link-layer interface in place of the raw socket interface. It's mainly a trade of power and complexity for ease of use. The link-layer interface is slightly more complex and requires a bit more coding. The raw socket interface is simpler and quicker to employ. Both require some forethought as to how much memory to allocate (see the section on packet construction).
A standard invocation of either interface might include the following:
raw socket interface
|
link-layer interface
|
| libnet_init_packet(); |
libnet_init_packet(); |
| libnet_open_raw_sock(); |
libnet_open_link_interface(); |
| libnet_build_ip(); |
libnet_build_ethernet(); |
| libnet_build_tcp(); |
libnet_build_ip(); |
| libnet_do_checksum(); |
libnet_build_tcp(); |
| libnet_write_ip(); |
libnet_do_checksum(); (IP) |
| |
libnet_do_checksum(); (TCP) |
| |
libnet_write_link_layer(); |
|