|
Packit |
03b34a |
===============================================================================
|
|
Packit |
03b34a |
$Id: DESIGN_NOTES,v 1.3 2004/01/17 07:51:19 mike Exp $
|
|
Packit |
03b34a |
LIBNET 1.1 (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
|
|
Packit |
03b34a |
http://www.packetfactory.net/libnet
|
|
Packit |
03b34a |
===============================================================================
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
DESIGN NOTES
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
In order to remove most of the decisions a user had to make (how much
|
|
Packit |
03b34a |
memory to allocate for a packet, where to build the packet headers, where
|
|
Packit |
03b34a |
to do the checksums, how to inject the packet, etc) I decided to move ALL
|
|
Packit |
03b34a |
of that logic into the library, behind the scenes. To initialize
|
|
Packit |
03b34a |
things and get an initial libnet context, the applications programmer
|
|
Packit |
03b34a |
calls:
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_t *l;
|
|
Packit |
03b34a |
l = libnet_init(INJECTION_TYPE, PROTOCOL, DEVICE, ERRBUFFER);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
where:
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
INJECTION_TYPE = LIBNET_RAW4 (ipv4 raw socket)
|
|
Packit |
03b34a |
LIBNET_RAW6 (ipv6 raw socket)
|
|
Packit |
03b34a |
LIBNET_LINK (link-layer socket)
|
|
Packit |
03b34a |
LIBNET_RAW4_ADV (advanced mode)
|
|
Packit |
03b34a |
LIBNET_RAW6_ADV (advanced mode)
|
|
Packit |
03b34a |
LIBNET_LINK_ADV (advanced mode)
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
PROTOCOL = IP protocol to be used for the raw socket. This is
|
|
Packit |
03b34a |
ignored for the link-layer, and almost always
|
|
Packit |
03b34a |
IPPROTO_RAW for ipv4.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
DEVICE = The canoical name of the device, used only with the link
|
|
Packit |
03b34a |
layer stuff. For ipv4 raw socket, you can leave this
|
|
Packit |
03b34a |
NULL. If it's NULL with the link-layer, libnet will try
|
|
Packit |
03b34a |
to find a suitable device.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
ERRBUFFER = Until we have our libnet context l, this is where
|
|
Packit |
03b34a |
errors will be.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
Inside of this newly created context we have a ton of stuff including a
|
|
Packit |
03b34a |
file descriptor for the packet device the injection type, the device name
|
|
Packit |
03b34a |
(if applicable) a pointer to the libnet protocol block structure and some
|
|
Packit |
03b34a |
other ancillary data.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
Additionally, we will soon be supporting context manipulation functions
|
|
Packit |
03b34a |
that will allow the user to set certain flags inside the context. This
|
|
Packit |
03b34a |
interface will be akin to libnet_toggle_checksum() for those of you who
|
|
Packit |
03b34a |
care.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
When a packet is first constructed, the protocol block (pblock) stuff comes
|
|
Packit |
03b34a |
into play. On the outside, to an applications programmer, a packet is
|
|
Packit |
03b34a |
constructed more or less like normal (with a few notable exceptions):
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t ip_tag;
|
|
Packit |
03b34a |
ip_tag = libnet_build_ipv4(
|
|
Packit |
03b34a |
LIBNET_UDP_H,
|
|
Packit |
03b34a |
0,
|
|
Packit |
03b34a |
242,
|
|
Packit |
03b34a |
0,
|
|
Packit |
03b34a |
64,
|
|
Packit |
03b34a |
IPPROTO_UDP,
|
|
Packit |
03b34a |
0, /* NEW: checksum */
|
|
Packit |
03b34a |
src_ip,
|
|
Packit |
03b34a |
dst_ip,
|
|
Packit |
03b34a |
NULL,
|
|
Packit |
03b34a |
0,
|
|
Packit |
03b34a |
l, /* NEW: libnet context */
|
|
Packit |
03b34a |
0 /* NEW: libnet ptag */
|
|
Packit |
03b34a |
);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
The checksum allows an applications programmer to decide if he wants to
|
|
Packit |
03b34a |
specify his own random value (useful in NIDS fooling) or precompute the
|
|
Packit |
03b34a |
sum elsewhere, or leave it zero and by default libnet will take care of it
|
|
Packit |
03b34a |
(although this is over-ridable). The libnet context is the opague
|
|
Packit |
03b34a |
pointer we allocated earlier and will show up in just about every libnet
|
|
Packit |
03b34a |
function call from here on out. The libnet ptag is a way to reference an
|
|
Packit |
03b34a |
ALREADY BUILT protocol block. This is necessary if you want to change
|
|
Packit |
03b34a |
some values of a header inside of a packet injection loop.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
So, when you call a build function, internally, it's a completely new
|
|
Packit |
03b34a |
system. If the item you're constructing is NEW, a new pblock will be
|
|
Packit |
03b34a |
allocated and linked onto the end of the list. It may be helpful to think
|
|
Packit |
03b34a |
of this as a "protocol stack" because you MUST build your packets IN
|
|
Packit |
03b34a |
ORDER, from the top of the protocol stack on down (i.e.: tcp -> ip ->
|
|
Packit |
03b34a |
ethernet). Once you build a new protocol block, it's "pushed down on the
|
|
Packit |
03b34a |
stack" and you move on to the next. However, this analogy breaks down
|
|
Packit |
03b34a |
because you can modify any one of these items and when they're assembled
|
|
Packit |
03b34a |
for the final packet, libnet starts at the head of the list. It may be
|
|
Packit |
03b34a |
MORE helpful to think of the pblock chain as a doubly linked FIFO
|
|
Packit |
03b34a |
queue, because that's what it is. :)
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
For example:
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t 1;
|
|
Packit |
03b34a |
libnet_ptag_t 2;
|
|
Packit |
03b34a |
libnet_ptag_t 3;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
1 = libnet_build_data(blah, l, 0);
|
|
Packit |
03b34a |
2 = libnet_build_tcp(blah, l, 0);
|
|
Packit |
03b34a |
3 = libnet_build_ipv4(blah, l, 0);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
Will result in:
|
|
Packit |
03b34a |
---------- ---------- ----------
|
|
Packit |
03b34a |
l->protocol_blocks--->| data |----->| tcp |----->| ip |
|
|
Packit |
03b34a |
| pblock |<-----| pblock |<-----| pblock |----|
|
|
Packit |
03b34a |
--| ptag: 1| | ptag: 2| | ptag: 3| |
|
|
Packit |
03b34a |
| ---------- ---------- ---------- v
|
|
Packit |
03b34a |
| -----
|
|
Packit |
03b34a |
|-------------------------------------------> ---
|
|
Packit |
03b34a |
-
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
To access and change the ip header, an additional call to libnet_build_ipv4
|
|
Packit |
03b34a |
with the ptag argument would be made:
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_build_ipv4(blah..., l, 3);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
Note that the ptag DOES NOT CHANGE. Once a pblock is built, its tag is
|
|
Packit |
03b34a |
set in stone.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
When it comes time to write the packet to the wire,
|
|
Packit |
03b34a |
libnet_pblock_coalesce() is called to assemble the packet fragments.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
1) Gather up all of the pblock sizes in order to allocate one
|
|
Packit |
03b34a |
contiguous block of memory.
|
|
Packit |
03b34a |
2) Copy over the packet fragments.
|
|
Packit |
03b34a |
3) Check each pblock to see which items need checksums, then perform
|
|
Packit |
03b34a |
that checksum over each portion (the entire packet is needed for
|
|
Packit |
03b34a |
some checksums).
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
So that's a quick description of what's going on under the hood. There's
|
|
Packit |
03b34a |
more, but this should be enough to get you started.
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
EOF
|