summaryrefslogtreecommitdiff
path: root/doc/MIGRATION.md
blob: 9a1863fb66890543c44d5d4bad79e649d2939944 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
Migrating Your Code to libnet 1.1 or Later
==========================================
by Mike D. Schiffman <mike@infonexus.com>

Using Libnet 1.1 you will find it MUCH simpler to build and write packets than
before.  Instead of the previous five steps (initialize memory, initialize
network, build packet, do checksums, write packet) there are now only three
steps (initialize library, build packet, write packet).

In order to port your existing code, you will mainly be *removing* function
calls and variables.


Cleanup
-------

Start with code removal:

- Remove all calls to `libnet_init_packet()` packet `malloc()`ing, and all
  associated variables
- Remove all calls to `libnet_open_raw_sock()`, `libnet_open_link_layer()`,
  and all associated variables
- Remove all calls to `libnet_do_checksum()` and all associated variables


Code Changes
------------

Continue with code addition and modification.

You will need a single `libnet_t *l` which is your libnet file context and an
error buffer:

    libnet_t *l
    char errbuf[LIBNET_ERRBUF_SIZE];

    l = libnet_init(
            LIBNET_RAW4,    /* or LIBNET_LINK or LIBNET_RAW6 */
            NULL,           /* or device if you using LIBNET_LINK */
            errbuf);

The `libnet_build_*()` functions are largely unchanged with a few important
differences:

1. Packets headers *MUST* be stacked *IN ORDER*.  This is intuitive and
   shouldn't be a problem.  Due to the way individual packet header memory is
   allocated and how packet pieces are combined to build a packet they *HAVE*
   to be built *IN ORDER*, from the high end of the protocol stack on down.
   i.e.: using the raw interface to build a NTP packet, you would:

        libnet_build_ntp(...)
        libnet_build_udp(...)
        libnet_build_ipv4(...)

   To build the same packet using the LINK interface on top of ethernet you
   would:

        libnet_build_ntp(...)
        libnet_build_udp(...)
        libnet_build_ipv4(...)
        libnet_build_ethernet(...)

   > **Note:** There is the option now of using `libnet_autobuild_ipv4()` and
   > `libnet_autobuild_ethernet()` which have fewer arguments and smaller
   > stack frames, and are a bit more convenient.

2. The `libnet_build_*()` functions return a `libnet_ptag_t` datatype on
   success or -1 on error.  This ptag is your "protocol/packet tag" so you can
   find this header again if you needed to modify it later on.  If you don't
   need to modify the packet header you can throw this value away.  You should
   definitely check for error now on your build functions.  A lot's going on
   down there fellas.

   > **Note:** that after packets are built, they may be accessed
   > independently of construction order via the saved ptag.

3. They *NO LONGER ACCEPT BUFFER ARGUMENTS*.  This is *ALL* done internally.
   The last *TWO* arguments are the libnet context you created in your call to
   `libnet_init()` and an *OPTIONAL* ptag argument.  The ptag argument, if
   non-zero, specifes a packet tag to an *ALREADY EXISTING* packet header that
   will be *OVERWRITTEN* with the values specified in this `libnet_build_*()`
   function call.  This is how you modify existing packet header pieces.  If
   this ptag is 0, a new protocol block is allocated and the packet is pushed
   down on the "protocol stack".
4. For the functions that build headers that have checksums these are *NOW
   SPECIFIED AS AN ARGUMENT*.  This adds more flexibility in how checksums are
   done (you can leave the field 0, put in a random value, precompute it on
   your own, or let the library do it).  By default, when you build a header,
   a `DO_CHECKSUM` flag will be set.  This means the library will compute the
   checksum for the header and possibly over the data before the packet is
   written.  To clear this flag, there is a special macro you can call on the
   ptag refering to that header.
5. For the functions that have a length, it now specifies the *TOTAL* packet
   length from that protocol unit on down.  For IP, that would be the entire
   packet length.  For TCP, that would be TCP and any possible data.
6. Nomenclature support for the eventual support of ipv6 has been added.

### Example

    libnet_ptag_t ip_tag;
    libnet_ptag_t tcp_tag;

    tcp_tag = libnet_build_tcp(
        src_prt,            /* source TCP port */
        dst_prt,            /* destination TCP port */
        0xffff,             /* sequence number */
        0x53,               /* acknowledgement number */
        TH_SYN,             /* control flags */
        1024,               /* window size */
        0xd00d,             /* checksum */
        0,                  /* urgent pointer */
        LIBNET_TCP_H        /* TCP packet size */
        NULL,               /* payload (none) */
        0,                  /* payload length */
        l,                  /* libnet context */
        0);                 /* ptag */

    ip_tag = libnet_build_ipv4(
        LIBNET_TCP_H + LIBNET_IPV4_H,/* total packet len */
        IPTOS_LOWDELAY,     /* tos */
        ip_id,              /* IP ID */
        0,                  /* IP Frag */
        64,                 /* TTL */
        IPPROTO_TCP,        /* protocol */
        0,                  /* checksum */
        src_ip,             /* source ip */
        dst_ip,             /* dest ip */
        NULL,               /* payload (none) */
        0,                  /* payload size */
        l,                  /* libnet context */
        0);                 /* ptag */

Now, if you wanted to modify one of these headers in a loop somewhere you
would:

    int i;
    for (ip_tag, tcp_tag = LIBNET_PTAG_INITIALIZER, i = 0; i < 10; i++)
    {
        tcp_tag = libnet_build_tcp(++src_prt, ..., l, tcp_tag);
        ip_tag = libnet_build_ipv4(..., ++ip_id, ..., l, ip_tag);
        /* do something */
    }

Since we are specifying a ptag for an existing header, the build function will
NOT create a new header and append it to the list, it will FIND the one
referenced by the ptag and *UPDATE* it.  Since there is nothing new being
created, order is NOT important here.

Also note that it's perfectly fine to wrap the loop around the initial
building of the packets.  Since we're initializing the ptags (to be zero), the
first call into the builder functions will allocate the memory and create the
packet blocks.  These calls will return ptag values.  The next calls will
modify these headers since the ptags will not be NULL.

### Writing the Packet

Finally, we write the packet.  Checksums are computed, by default for each
protocol header that requires one.  If the user specifies a non-zero value, by
default, this will be used *INSTEAD* of a libnet computed checksum.  This
behavior is possible to override with:
  
Turn ON checksums for header referenced by ptag:

    libnet_toggle_checksum(l, ptag, 1)

Turn OFF checksums for header referenced by ptag:

    libnet_toggle_checksum(l, ptag, 0)

Note, the packet header MUST exist before you can toggle this setting.

    int c;
    c = libnet_write(l);

Boom.  You're done.  Now go read the sample code.