Content-type: text/html Manpage of LIBPNET6


Section: LIBPNET6 API Reference (3)
Updated: March 30, 2003
Index Return to Main Contents



 - libpnet6's functionality that can be used to send TCP datagrams. See pnet6(3) for an introduction to libpnet6.



# include <pnet6.h>
# include <pnet6tlp.h>

NOTE: in order to be able to follow this, some familiarity with IP datagrams and the TCP/IP protocol is required (and assumed in this document). Please, read through pnet6-ip(3), first if you need to know the format and functions necessary to work with raw IP datagrams.



Libpnet6 provides a few simple functions to facilitate the construction of TCP datagrams for use with IPv4 and IPv6 sockets. Such datagrams can then be sent on a raw socket, making it possible to make and send your own TCP datagrams.



A TCP datagram-header is represented by the following structure in libpnet6:

typedef pnet_uint       pnet_tcpseq;
typedef struct _tcp_header {
        pnet_ushort th_sport; /* Source port of datagram */
        pnet_ushort th_dport; /* Destination port of datagram */
        pnet_tcpseq th_seq;   /* Datagram sequence number */
        pnet_tcpseq th_ack;   /* Datagram ack number */
        pnet_byte   th_x2off; /* Data offset and reserved flags */
        pnet_byte   th_flags; /* TCP flags, see below */
        pnet_ushort th_win;   /* Advertised window size */
        pnet_ushort th_sum;   /* Datagram checksum */
        pnet_ushort th_urp;   /* Urgent data pointer */
} pnet_tcp;

#define TH_FIN    0x01
#define TH_SYN    0x02
#define TH_RST    0x04
#define TH_PUSH   0x08
#define TH_ACK    0x10
#define TH_URG    0x20
#define TH_CE     0x40   /* Explicit Congestion Notification CWR bit */
#define TH_CC     0x80   /* Explicit Congestion Notification CWR bit */

Although this header and its members can be accessed directly, it is easier to use the accessor functions that libpnet6 provides. Not only are you spared the details of byte ordering issues, you also don't need to worry about proper packing of all the data.

Accessor Functions

int pnetTCP_Build( pnet_tcp* tcp, pnet_ushort srcport, pnet_ushort dstport, pnet_tcpseq seq, pnet_tcpseq ack, pnet_byte ecn, pnet_byte flags, pnet_ushort win, pnet_ushort chksum, pnet_ushort );

This function builds a TCP header. The header is passed as the first argument, and when the function returns its members are filled out properly with the valeus passed with the given arguments. Most of the other arguments are self-explanatory and have a direct correspondence with the members of the TCP header as shown earlier. The only weird one is ecn, which have to do with TCP's Explicit Congenstion Notification (see RFC 3168 for more info).

The chksum can be set to 0, in which case libpnet6 will compute and set it prior to sending the datagram. If you pass a value other than 0, then this value will be used instead.

This function always succeeds (although it does return a value of 0 to indicate success).

pnet_ushort pnetTCP_ComputeChecksum( void * pip, pnet_tcp * tcp );

Computes a TCP datagram' checksum. The first argument must be a pointer to a valid IPv4 or IPv6 datagram (for examples as returned by one of the IP building functions described in pnet6-ip(3)).

This function assumes that the payload of the TCP datagram follows immediately after the tcp header in contiguous memory. Also, the IP datagram length should be correctly set to account for the length of the TCP header plus its payload.

This function correctly computes the TCP pseudo checksum, depending on whether the first argument is an IPv4 or IPv6 datagram.

int pnetTCP_Send( PNETSOCK * ps, PNETADDR pa, void * pip, pnet_tcp * tcp, byte * buf, int buflen );

Sends a TCP datagram on the given raw socket to the given address. pip is a pointer to a valid IPv4 or IPv6 datagram; the socket must be a raw socket of an address family matching that of the IP datagram's type (i.e. IPv4 or IPv6); tcp must have been built by pnetTCP_Build(). The last two arguments are the actual data to be sent as the TCP datagram's payload, and its length. This length does not include any of the TCP or IP headers that are prepended to it.


The following macros are useful for accessing the different parts of a TCP header.

int pnetTCP_DataOffset( pnet_tcp * tcp);

Returns the offset to the TCP datagrams data counting from the start of the TCP header (in fact, this value is the length of the TCP header, in bytes).

int pnetTCP_HeaderLength( pnet_tcp * tcp);

Returns the length of the TCP header. See pnetTCP_DataOffset().

pnet_ushort pnetTCP_SrcPort( pnet_tcp * tcp);

pnet_ushort pnetTCP_DstPort( pnet_tcp * tcp);

Return the source and destination port of the TCP datagram, respectively.

pnet_tcpseq pnetTCP_Seq( pnet_tcp * tcp); pnet_tcpseq pnetTCP_Ack( pnet_tcp * tcp);

Return the sequence (acknowledgment) number of this TCP header.

pnet_ushort pnetTCP_Win( pnet_tcp * tcp);

Returns the advertised window size of this TCP header.

pnet_ushort pnetTCP_Checksum( pnet_tcp * tcp);

Returns the value of the checksum for this TCP header.

int pnetTCP_Fin( pnet_tcp * tcp);

int pnetTCP_Syn( pnet_tcp * tcp);

int pnetTCP_Rst( pnet_tcp * tcp);

int pnetTCP_Push( pnet_tcp * tcp);

int pnetTCP_Urg( pnet_tcp * tcp);

int pnetTCP_Cwr( pnet_tcp * tcp);

int pnetTCP_Ece( pnet_tcp * tcp);

Each of these functions returns 1 if the corresponding flag (defined above) is set for this datagram.

pnet_byte * pnetTCP_Opts( pnet_tcp * tcp);

Returns a pointer to the TCP header options.

pnet_uint * pnetTCP_OptsLen( pnet_tcp * tcp);

Returns the length of the TCP header options, in bytes.



An example of building and sending raw TCP/IP datagrams is given in the tests/raw/raw.c file in the main libpnet6 distribution.

Here's and example of how to parse TCP header options (taken from the example contained in the examples/snoop/snoop.c directory of the main libpnet6 distribution).

pnet_byte * popts;
int         optlen;
optlen = pnetTCP_OptsLen( tcp );
popts  = pnetTCP_Opts( tcp );

while ( optlen > 0 ) {
    switch ( *popts ) {
    case 0: printf("eoo"); break;
    case 1: printf("nop,"); break;
    case 2:
        printf("mss: %d,", pnet_ntohs( *(pnet_ushort*)( popts + 2 )));
    case 3:
        printf("wsf: %d,", *(popts + 2));
    case 4:
        printf("sack,"); break;
    case 5:
        printf("sack block,"); break;
    case 6:
        printf("echo,"); break;
    case 7:
        printf("echoreply,"); break;
    case 8:
        printf("tstamp,"); break;
    case 9:
        printf("partial order connection permitted,"); break;
    case 10:
        printf("partial order service profile %d,",*(popts + 2));
    case 11: printf("CC,"); break;
    case 12: printf("CC new,"); break;
    case 13: printf("CC echo,"); break;
    case 14:
        printf("Alt. chksum req.=%d,",*(popts + 2));
    case 15:
        printf("Alt. chksum data,");
    if ( *popts < 2 )
        popts++, optlen--;
    else {
        optlen -= *(popts + 1);
        popts += *(popts + 1);



pnet6(3), pnet6-addr(3), pnet6-api(3), pnet6-aux(3), pnet6-if(3), pnet6-ip(3), pnet6-log(3), pnet6-pkt(3), pnet6-raw(3), pnet6-socket(3), pnet6-tcp(3), pnet6-threads(3), pnet6-udp(3).



The current version of libpnet6 is highly experimental.

You can always get the most recent version from





Peter Bozarov. Send mail to kingofgib (at)




This document was created by man2html, using the manual pages.
Time: 06:22:19 GMT, May 26, 2003