Annotation of embedaddon/libnet/doc/DESIGN_NOTES, revision 1.1.1.1
1.1 misho 1: ===============================================================================
2: $Id: DESIGN_NOTES,v 1.3 2004/01/17 07:51:19 mike Exp $
3: LIBNET 1.1 (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
4: http://www.packetfactory.net/libnet
5: ===============================================================================
6:
7:
8: DESIGN NOTES
9:
10: In order to remove most of the decisions a user had to make (how much
11: memory to allocate for a packet, where to build the packet headers, where
12: to do the checksums, how to inject the packet, etc) I decided to move ALL
13: of that logic into the library, behind the scenes. To initialize
14: things and get an initial libnet context, the applications programmer
15: calls:
16:
17: libnet_t *l;
18: l = libnet_init(INJECTION_TYPE, PROTOCOL, DEVICE, ERRBUFFER);
19:
20: where:
21:
22: INJECTION_TYPE = LIBNET_RAW4 (ipv4 raw socket)
23: LIBNET_RAW6 (ipv6 raw socket)
24: LIBNET_LINK (link-layer socket)
25: LIBNET_RAW4_ADV (advanced mode)
26: LIBNET_RAW6_ADV (advanced mode)
27: LIBNET_LINK_ADV (advanced mode)
28:
29: PROTOCOL = IP protocol to be used for the raw socket. This is
30: ignored for the link-layer, and almost always
31: IPPROTO_RAW for ipv4.
32:
33: DEVICE = The canoical name of the device, used only with the link
34: layer stuff. For ipv4 raw socket, you can leave this
35: NULL. If it's NULL with the link-layer, libnet will try
36: to find a suitable device.
37:
38: ERRBUFFER = Until we have our libnet context l, this is where
39: errors will be.
40:
41: Inside of this newly created context we have a ton of stuff including a
42: file descriptor for the packet device the injection type, the device name
43: (if applicable) a pointer to the libnet protocol block structure and some
44: other ancillary data.
45:
46: Additionally, we will soon be supporting context manipulation functions
47: that will allow the user to set certain flags inside the context. This
48: interface will be akin to libnet_toggle_checksum() for those of you who
49: care.
50:
51: When a packet is first constructed, the protocol block (pblock) stuff comes
52: into play. On the outside, to an applications programmer, a packet is
53: constructed more or less like normal (with a few notable exceptions):
54:
55: libnet_ptag_t ip_tag;
56: ip_tag = libnet_build_ipv4(
57: LIBNET_UDP_H,
58: 0,
59: 242,
60: 0,
61: 64,
62: IPPROTO_UDP,
63: 0, /* NEW: checksum */
64: src_ip,
65: dst_ip,
66: NULL,
67: 0,
68: l, /* NEW: libnet context */
69: 0 /* NEW: libnet ptag */
70: );
71:
72: The checksum allows an applications programmer to decide if he wants to
73: specify his own random value (useful in NIDS fooling) or precompute the
74: sum elsewhere, or leave it zero and by default libnet will take care of it
75: (although this is over-ridable). The libnet context is the opague
76: pointer we allocated earlier and will show up in just about every libnet
77: function call from here on out. The libnet ptag is a way to reference an
78: ALREADY BUILT protocol block. This is necessary if you want to change
79: some values of a header inside of a packet injection loop.
80:
81: So, when you call a build function, internally, it's a completely new
82: system. If the item you're constructing is NEW, a new pblock will be
83: allocated and linked onto the end of the list. It may be helpful to think
84: of this as a "protocol stack" because you MUST build your packets IN
85: ORDER, from the top of the protocol stack on down (i.e.: tcp -> ip ->
86: ethernet). Once you build a new protocol block, it's "pushed down on the
87: stack" and you move on to the next. However, this analogy breaks down
88: because you can modify any one of these items and when they're assembled
89: for the final packet, libnet starts at the head of the list. It may be
90: MORE helpful to think of the pblock chain as a doubly linked FIFO
91: queue, because that's what it is. :)
92:
93: For example:
94:
95: libnet_ptag_t 1;
96: libnet_ptag_t 2;
97: libnet_ptag_t 3;
98:
99: 1 = libnet_build_data(blah, l, 0);
100: 2 = libnet_build_tcp(blah, l, 0);
101: 3 = libnet_build_ipv4(blah, l, 0);
102:
103: Will result in:
104: ---------- ---------- ----------
105: l->protocol_blocks--->| data |----->| tcp |----->| ip |
106: | pblock |<-----| pblock |<-----| pblock |----|
107: --| ptag: 1| | ptag: 2| | ptag: 3| |
108: | ---------- ---------- ---------- v
109: | -----
110: |-------------------------------------------> ---
111: -
112:
113: To access and change the ip header, an additional call to libnet_build_ipv4
114: with the ptag argument would be made:
115:
116: libnet_build_ipv4(blah..., l, 3);
117:
118: Note that the ptag DOES NOT CHANGE. Once a pblock is built, its tag is
119: set in stone.
120:
121: When it comes time to write the packet to the wire,
122: libnet_pblock_coalesce() is called to assemble the packet fragments.
123:
124: 1) Gather up all of the pblock sizes in order to allocate one
125: contiguous block of memory.
126: 2) Copy over the packet fragments.
127: 3) Check each pblock to see which items need checksums, then perform
128: that checksum over each portion (the entire packet is needed for
129: some checksums).
130:
131: So that's a quick description of what's going on under the hood. There's
132: more, but this should be enough to get you started.
133:
134: EOF
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>