Annotation of embedaddon/libnet/doc/MIGRATION.md, revision 1.1.1.1

1.1       misho       1: Migrating Your Code to libnet 1.1 or Later
                      2: ==========================================
                      3: by Mike D. Schiffman <mike@infonexus.com>
                      4: 
                      5: Using Libnet 1.1 you will find it MUCH simpler to build and write packets than
                      6: before.  Instead of the previous five steps (initialize memory, initialize
                      7: network, build packet, do checksums, write packet) there are now only three
                      8: steps (initialize library, build packet, write packet).
                      9: 
                     10: In order to port your existing code, you will mainly be *removing* function
                     11: calls and variables.
                     12: 
                     13: 
                     14: Cleanup
                     15: -------
                     16: 
                     17: Start with code removal:
                     18: 
                     19: - Remove all calls to `libnet_init_packet()` packet `malloc()`ing, and all
                     20:   associated variables
                     21: - Remove all calls to `libnet_open_raw_sock()`, `libnet_open_link_layer()`,
                     22:   and all associated variables
                     23: - Remove all calls to `libnet_do_checksum()` and all associated variables
                     24: 
                     25: 
                     26: Code Changes
                     27: ------------
                     28: 
                     29: Continue with code addition and modification.
                     30: 
                     31: You will need a single `libnet_t *l` which is your libnet file context and an
                     32: error buffer:
                     33: 
                     34:     libnet_t *l
                     35:     char errbuf[LIBNET_ERRBUF_SIZE];
                     36: 
                     37:     l = libnet_init(
                     38:             LIBNET_RAW4,    /* or LIBNET_LINK or LIBNET_RAW6 */
                     39:             NULL,           /* or device if you using LIBNET_LINK */
                     40:             errbuf);
                     41: 
                     42: The `libnet_build_*()` functions are largely unchanged with a few important
                     43: differences:
                     44: 
                     45: 1. Packets headers *MUST* be stacked *IN ORDER*.  This is intuitive and
                     46:    shouldn't be a problem.  Due to the way individual packet header memory is
                     47:    allocated and how packet pieces are combined to build a packet they *HAVE*
                     48:    to be built *IN ORDER*, from the high end of the protocol stack on down.
                     49:    i.e.: using the raw interface to build a NTP packet, you would:
                     50: 
                     51:         libnet_build_ntp(...)
                     52:         libnet_build_udp(...)
                     53:         libnet_build_ipv4(...)
                     54: 
                     55:    To build the same packet using the LINK interface on top of ethernet you
                     56:    would:
                     57: 
                     58:         libnet_build_ntp(...)
                     59:         libnet_build_udp(...)
                     60:         libnet_build_ipv4(...)
                     61:         libnet_build_ethernet(...)
                     62: 
                     63:    > **Note:** There is the option now of using `libnet_autobuild_ipv4()` and
                     64:    > `libnet_autobuild_ethernet()` which have fewer arguments and smaller
                     65:    > stack frames, and are a bit more convenient.
                     66: 
                     67: 2. The `libnet_build_*()` functions return a `libnet_ptag_t` datatype on
                     68:    success or -1 on error.  This ptag is your "protocol/packet tag" so you can
                     69:    find this header again if you needed to modify it later on.  If you don't
                     70:    need to modify the packet header you can throw this value away.  You should
                     71:    definitely check for error now on your build functions.  A lot's going on
                     72:    down there fellas.
                     73: 
                     74:    > **Note:** that after packets are built, they may be accessed
                     75:    > independently of construction order via the saved ptag.
                     76: 
                     77: 3. They *NO LONGER ACCEPT BUFFER ARGUMENTS*.  This is *ALL* done internally.
                     78:    The last *TWO* arguments are the libnet context you created in your call to
                     79:    `libnet_init()` and an *OPTIONAL* ptag argument.  The ptag argument, if
                     80:    non-zero, specifes a packet tag to an *ALREADY EXISTING* packet header that
                     81:    will be *OVERWRITTEN* with the values specified in this `libnet_build_*()`
                     82:    function call.  This is how you modify existing packet header pieces.  If
                     83:    this ptag is 0, a new protocol block is allocated and the packet is pushed
                     84:    down on the "protocol stack".
                     85: 4. For the functions that build headers that have checksums these are *NOW
                     86:    SPECIFIED AS AN ARGUMENT*.  This adds more flexibility in how checksums are
                     87:    done (you can leave the field 0, put in a random value, precompute it on
                     88:    your own, or let the library do it).  By default, when you build a header,
                     89:    a `DO_CHECKSUM` flag will be set.  This means the library will compute the
                     90:    checksum for the header and possibly over the data before the packet is
                     91:    written.  To clear this flag, there is a special macro you can call on the
                     92:    ptag refering to that header.
                     93: 5. For the functions that have a length, it now specifies the *TOTAL* packet
                     94:    length from that protocol unit on down.  For IP, that would be the entire
                     95:    packet length.  For TCP, that would be TCP and any possible data.
                     96: 6. Nomenclature support for the eventual support of ipv6 has been added.
                     97: 
                     98: ### Example
                     99: 
                    100:     libnet_ptag_t ip_tag;
                    101:     libnet_ptag_t tcp_tag;
                    102: 
                    103:     tcp_tag = libnet_build_tcp(
                    104:         src_prt,            /* source TCP port */
                    105:         dst_prt,            /* destination TCP port */
                    106:         0xffff,             /* sequence number */
                    107:         0x53,               /* acknowledgement number */
                    108:         TH_SYN,             /* control flags */
                    109:         1024,               /* window size */
                    110:         0xd00d,             /* checksum */
                    111:         0,                  /* urgent pointer */
                    112:         LIBNET_TCP_H        /* TCP packet size */
                    113:         NULL,               /* payload (none) */
                    114:         0,                  /* payload length */
                    115:         l,                  /* libnet context */
                    116:         0);                 /* ptag */
                    117: 
                    118:     ip_tag = libnet_build_ipv4(
                    119:         LIBNET_TCP_H + LIBNET_IPV4_H,/* total packet len */
                    120:         IPTOS_LOWDELAY,     /* tos */
                    121:         ip_id,              /* IP ID */
                    122:         0,                  /* IP Frag */
                    123:         64,                 /* TTL */
                    124:         IPPROTO_TCP,        /* protocol */
                    125:         0,                  /* checksum */
                    126:         src_ip,             /* source ip */
                    127:         dst_ip,             /* dest ip */
                    128:         NULL,               /* payload (none) */
                    129:         0,                  /* payload size */
                    130:         l,                  /* libnet context */
                    131:         0);                 /* ptag */
                    132: 
                    133: Now, if you wanted to modify one of these headers in a loop somewhere you
                    134: would:
                    135: 
                    136:     int i;
                    137:     for (ip_tag, tcp_tag = LIBNET_PTAG_INITIALIZER, i = 0; i < 10; i++)
                    138:     {
                    139:         tcp_tag = libnet_build_tcp(++src_prt, ..., l, tcp_tag);
                    140:         ip_tag = libnet_build_ipv4(..., ++ip_id, ..., l, ip_tag);
                    141:         /* do something */
                    142:     }
                    143: 
                    144: Since we are specifying a ptag for an existing header, the build function will
                    145: NOT create a new header and append it to the list, it will FIND the one
                    146: referenced by the ptag and *UPDATE* it.  Since there is nothing new being
                    147: created, order is NOT important here.
                    148: 
                    149: Also note that it's perfectly fine to wrap the loop around the initial
                    150: building of the packets.  Since we're initializing the ptags (to be zero), the
                    151: first call into the builder functions will allocate the memory and create the
                    152: packet blocks.  These calls will return ptag values.  The next calls will
                    153: modify these headers since the ptags will not be NULL.
                    154: 
                    155: ### Writing the Packet
                    156: 
                    157: Finally, we write the packet.  Checksums are computed, by default for each
                    158: protocol header that requires one.  If the user specifies a non-zero value, by
                    159: default, this will be used *INSTEAD* of a libnet computed checksum.  This
                    160: behavior is possible to override with:
                    161:   
                    162: Turn ON checksums for header referenced by ptag:
                    163: 
                    164:     libnet_toggle_checksum(l, ptag, 1)
                    165: 
                    166: Turn OFF checksums for header referenced by ptag:
                    167: 
                    168:     libnet_toggle_checksum(l, ptag, 0)
                    169: 
                    170: Note, the packet header MUST exist before you can toggle this setting.
                    171: 
                    172:     int c;
                    173:     c = libnet_write(l);
                    174: 
                    175: Boom.  You're done.  Now go read the sample code.

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>