Introduction

Next Previous Top

5. Library Internals

This section is devoted to the internals of the library. First covered are all the user-accessible functions, then constants, macros and finally libnet-specific data structures.

Proceeding each function prototype is a small table listing the return values of the function, whether or not the function is reentrant (a function is considered reentrant if it may be called repeatedly, or may be called before previous invocations have completed, and each invocation is independent of all other invocations) and a brief description of the function's arguments.

5.1 Memory Management Functions

int libnet_init_packet(u_short packet_size, u_char **buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - desired packet size 2 - address of a u_char pointer

libnet_init_packet() creates memory for a packet (it doesn't so much create memory as it requests it from the underlying operating system via malloc()). Upon success the memory is zero-filled. The function accepts two arguments, the packet size and the address of the pointer to the packet. The packet size parameter may be 0, in which case the library will attempt to guess a packet size for you. Passing in the pointer to a pointer (passing by address) is necessary as we are allocating memory locally. If we instead passed in just a pointer (passing by value) the allocated memory would be lost.

This function is a good example of interface hiding. This function is essentially a malloc() wrapper. By using this function the details of what's really happening are abstracted so that you, the programmer, can worry about your task at hand.

void libnet_destroy_packet(u_char **buf);

return value upon success | NA
return value upon failure | NA
re-entrant | yes
arguments | 1 - address of a u_char pointer

libnet_destroy_packet() is the free() analog to libnet_init_packet. It destroys the packet referenced by 'buf'. In reality, it is of course a simple free() wrapper. It frees the heap memory and points `buf` to NULL to dispel the dangling pointer. The function does make the assertion that `buf` is not NULL. A pointer to a pointer is passed to maintain interface consistency.

int libnet_init_packet_arena(struct libnet_arena **arena, u_short packet_size, u_short packet_size);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - pointer to an arena structure pointer 2 - number of packets 3 - packet size

libnet_init_packet_arena() allocates and initializes a memory pool. If you plan on building and sending several different packets, this is a good choice. It allocates a pool of memory from which you can grab chunks to build packets (see next_packet_from_arena()). It takes the address to an arena structure pointer, and hints on the possible packet size and number of packets. The last two arguments are used to compute the size of the memory pool. As before, they can be set to 0 and the library will attempt to choose a decent value. The function returns -1 if the malloc fails or 1 if everything goes ok.

u_char *libnet_next_packet_from_arena(struct libnet_arena **arena, u_short packet_size);

return value upon success | pointer to the request packet memory
return value upon failure | NULL
re-entrant | yes
arguments | 1 - pointer to the arena 2 - requested packet size

libnet_next_packet_from_arena() returns a chunk of memory from the specified arena of the requested size and decrements the arenas available byte counter. If the requested memory is not available from the arena, the function returns NULL. Note that there is nothing preventing a poorly coded application from using more memory than requested and causing all kinds of problems. Take heed.

void libnet_destroy_packet_arena(struct libnet_arena **arena);

return value upon success | NA
return value upon failure | NA
re-entrant | yes
arguments | 1 - pointer to the arena

libnet_destroy_packet_arena() frees the memory associated with the specified arena.

5.2 Address Resolution Functions

u_char *libnet_host_lookup(u_long ip, u_short use_name);

return value upon success | pointer to the converted IP address
return value upon failure | NULL
re-entrant | no
arguments | 1 - network-byte ordered IP address 2 - use_name flag

libnet_host_lookup() converts the supplied network-ordered (big-endian) IP address into its human-readable counterpart. If the usename flag is LIBNET_RESOLVE, the function will attempt to resolve the IP address (possibly incurring DNS network traffic) and return a canonical hostname, otherwise if it is LIBNET_DONT_RESOLVE (or if the lookup fails), the function returns a dotted-decimal ASCII string. This function is hopelessly non reentrant as it uses static data.

void libnet_host_lookup_r(u_long ip, u_short use_name, u_char *buf);

return value upon success | NA
return value upon failure | NA
re-entrant | depends on architecture
arguments | 1 - network-byte ordered IP address 2 - use_name flag 3 - buffer to contain the converted IP address

libnet_host_lookup_r() is the planned reentrant version of the above function. If reentrant network resolver libraries become available, this function will likewise be reentrant. An additional argument of a buffer to store the converted (or resolved) IP address is supplied by the user.

u_long libnet_name_resolve(u_char *ip, u_short use_name);

return value upon success | network-byte ordered IP address
return value upon failure | -1
re-entrant | yes
arguments | 1 - human readable IP address or FQDN 2 - use_name flag

libnet_name_resolve() takes a NULL terminated ASCII string representation of an IP address (dots and decimals or, if the usename flag is LIBNET_RESOLVE, a canonical hostname) and converts it into a network-ordered (big-endian) unsigned long value.

u_long libnet_get_ipaddr(struct libnet_link_int *l, const u_char *device, const u_char *ebuf);

return value upon success | requested IP address
return value upon failure | -1
re-entrant | yes
arguments | 1 - pointer to a link interface structure 2 - pointer to the device to query 3 - pointer to a buffer to contain a possible error message

libnet_get_ipaddr() returns the IP address of a specified network device. The function takes a pointer to a link layer interface structure, a pointer to the network device name, and an empty buffer to be used in case of error. Upon success the function returns the IP address of the specified interface in network-byte order or 0 upon error (and errbuf will contain a reason).

struct ether_addr *libnet_get_hwaddr(struct libnet_link_int *l, const u_char *device, const u_char *ebuf);

return value upon success | pointer to the requested ethernet address
return value upon failure | NULL
re-entrant | depends on architecture
arguments | 1 - pointer to a link interface structure 2 - pointer to the device to query 3 - pointer to a buffer to contain a possible error message

libnet_get_hwaddr() returns the hardware address of a specified network device. At the time of this writing, only ethernet is supported. The function takes a pointer to a link layer interface structure, a pointer to the network device name, and an empty buffer to be used in case of error. The function returns the MAC address of the specified interface upon success or NULL upon error (and errbuf will contain a reason).

5.3 Packet Injection Support Functions

int libnet_open_raw_sock(int protocol);

return value upon success | opened socket
return value upon failure | -1
re-entrant | yes
arguments | 1 - protocol number of desired socket type

libnet_open_raw_sock() opens a raw IP socket of the specified protocol type (supported types vary from system to system, but usually you'll want to open an IPPROTO_RAW socket). The function also sets the IP_HDRINCL socket option. Returned is the socket file descriptor or -1 on error. The function can fail if either of the underlying calls to socket or setsockopt fails. Checking errno will reveal the reason for the error.

int libnet_close_raw_sock(int socket);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - socket to be closed

libnet_close_raw_sock() will close the referenced raw socket.

int libnet_select_device(struct sockaddr_in *sin, u_char **device, u_char *ebuf);

return value upon success | 1
return value upon failure | -1
re-entrant | no
arguments | 1 - pointer to a sockaddr_in structure pointer 2 - pointer to the device to query 3 - pointer to a buffer to contain a possible error message

libnet_select_device() will run through the list of interfaces and select one for use (ignoring the loopback device). If the device argument points to NULL (don't pass in a NULL pointer, the function expects a pointer to a pointer, and C can't derefrence a NULL pointer) it will try to fill it in with the first non-loopback device it finds, otherwise, it will try to open the specified device. If successful, 1 is returned (and if device was NULL, it will now contain the device name which can be used in libnet_*link*() type calls). The function can fail for a variety of reasons, including socket system call failures, ioctl failures, if no interfaces are found, etc.. If such an error occurs, -1 is returned and errbuf will contain a reason.

struct libnet_link_int *libnet_open_link_interface(char *device, char *ebuf);

return value upon success | pointer to a link interface structure
return value upon failure | NULL
re-entrant | yes
arguments | 1 - pointer to a device 2 - pointer to a buffer to contain a possible error message

libnet_open_link_interface() opens a low-level packet interface. This is required in order to be able inject link layer frames. Supplied is a u_char pointer to the interface device name and a u_char pointer to an error buffer. Returned is a filled-in link_int structure or NULL on error (with the error buffer containing the reason). The function can fail for a variety of reasons due to the fact that it is architecture specific.

int libnet_close_link_interface(struct libnet_link_int *l);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - pointer to a link interface structure

libnet_close_link_interface() closes an opened low-level packet interface.

int libnet_write_ip(int socket, u_char *packet, int packet_size);

return value upon success | packet size
return value upon failure | -1
re-entrant | yes
arguments | 1 - socket 2 - pointer to the packet 3 - packet size

libnet_write_ip() writes an IP packet to the network. The first argument is the socket created with a previous call to libnet_open_raw_sock, the second is a pointer to a buffer containing a complete IP datagram, and the third argument is the total packet size. The function returns the number of bytes written upon success or -1 on error (with errno containing the reason).

int libnet_write_link_layer(struct libnet_link_int *l, const u_char *device, u_char *packet, int packet_size);

return value upon success | packet size
return value upon failure | -1
re-entrant | depends on architecture
arguments | 1 - pointer to a link interface structure 2 - pointer to the network device 3 - pointer to the packet 4 - packet size

libnet_write_link_layer() writes a link-layer frame to the network. The first argument is a pointer to a filled-in libnet_link_int structure, the next is a pointer to the network device, the third is the raw packet and the last is the packet size. Returned is the number of bytes written or -1 on error.

int libnet_do_checksum(u_char *packet, int protocol, int packet_size);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - pointer to a packet 2 - protocol number of packet type 3 - packet size

libnet_do_checksum() calculates the checksum for a packet. The first argument is a pointer to a fully built IP packet. The second is the transport protocol of the packet and the third is the packet length (not including the IP header). The function calculates the checksum for the transport protocol and fills it in at the appropriate header location (this function should be called only after a complete packet has been built).

Note that when using raw sockets the IP checksum is always computed by the kernel and does not need to done by the user. When using the link layer interface the IP checksum must be explicitly computed (in this case, the protocol would be of type IPPROTO_IP and the size would include IP_H). The function returns 1 upon success or -1 if the protocol is of an unsupported type. Currently supported are:

VALUE | PROTOCOL
IPPROTO_TCP | TCP
IPPROTO_UDP | UDP
IPPROTO_ICMP | ICMP
IPPROTO_IGMP | IGMP
IPPROTO_IP | IP (for the link-layer api)
IPPROTO_OSPF | OSPF
IPPROTO_OSPF | OSPF_LSA

5.4 Packet Construction Functions

All libnet packet creation functions contain the same three terminal arguments: a pointer to an optional payload (or NULL if no payload is to be included), the length of the payload in bytes (or 0 if no payload is included) and most importantly, a pointer to a pre-allocated block of memory (which must be large enough to accommodate the entire packet and payload).

The only way for any libnet packet construction function will return an error is if the memory which is supposed to be pre-allocated points to NULL.

libnet_build_arp(u_short hrdw, u_short prot, u_short h_len, u_short p_len, u_short op, u_char *s_ha, u_char *s_pa, u_char *t_ha, u_char *t_pa, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - hardware address format (ARPHRD_ETHER) 2 - protocol address format 3 - length of the hardware address 4 - length of the protocol address 5 - ARP operation type 6 - sender's hardware address 7 - sender's protocol address 8 - target's hardware address 9 - target's protocol address 10 - pointer to packet payload 11 - packet payload length 12 - pointer to pre-allocated packet memory

libnet_build_arp() constructs an ARP (RARP) packet. At this point in the library, the function only builds ethernet/ARP packets, but this will be easy enough to change (whenever I get around to it). The first nine arguments are standard ARP header arguments, with the last three being standard libnet packet creation arguments. The ARP operation type should be one of the following symbolic types:

VALUE | DESCRIPTION
ARPOP_REQUEST | ARP request
ARPOP_REPLY | ARP reply
ARPOP_REVREQUEST | RARP request
ARPOP_REVREPLY | RARP reply
ARPOP_INVREQUEST | request to identify peer
ARPOP_INVREPLY | reply identifying peer

int libnet_build_dns(u_short id, u_short flags, u_short num_q, u_short num_answ_rr, u_short num_auth_rr, u_short num_add_rr, const u_char * payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - packet id 2 - control flags 3 - number of questions 4 - number of answer resource records 5 - number of authority resource records 6 - number of additional resource records 7 - pointer to packet payload 8 - packet payload length 9 - pointer to pre-allocated packet memory

libnet_build_dns() constructs a DNS packet. The static DNS fields are included as the first six arguments, but the optional variable length fields must be included with the payload interface.

int libnet_build_ethernet(u_char *daddr, u_char *saddr, u_short id, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - pointer to the destination address 2 - pointer to the source address 3 - ethernet packet type 4 - pointer to packet payload 5 - packet payload size 6 - pointer to pre-allocated packet memory

libnet_build_ethernet() constructs an ethernet packet. The destination address and source address arguments are expected to be arrays of unsigned character bytes. The packet type should be one of the following:

VALUE | PROTOCOL
ETHERTYPE_PUP | PUP
ETHERTYPE_IP | IP
ETHERTYPE_ARP | ARP
ETHERTYPE_REVARP | RARP
ETHERTYPE_VLAN | IEEE VLAN tagging
ETHERTYPE_LOOPBACK | loopback test

int libnet_build_icmp_echo(u_char type, u_char code, u_short id, u_short seq, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1- packet type 2 - packet code 3 - packet id 4 - packet sequence number 5 - pointer to packet payload 6 - packet payload size 7 - pointer to pre-allocated packet memory

libnet_build_icmp_echo() constructs an ICMP_ECHO / ICMP_ECHOREPLY packet. The packet type should be ICMP_ECHOREPLY or ICMP_ECHO and the code should be 0.

int libnet_build_icmp_mask(u_char type, u_char code, u_short id, u_short seq, u_long mask, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - packet type 2 - packet code 3 - packet id 4 - packet sequence number 5 - IP netmask 6 - pointer to packet payload 7 - packet payload length 8 - pointer to pre-allocated packet memory

libnet_build_icmp_mask() constructs an ICMP_MASKREQ / ICMP_MASKREPLY packet. The packet type should be either ICMP_MASKREQ or ICMP_MASKREPLY and the code should be 0. The IP netmask argument should be a 32-bit network-byte ordered subnet mask.

int libnet_build_icmp_unreach(u_char type, u_char code, u_short orig_len, u_char orig_tos, u_short orig_id, u_short orig_frag, u_char orig_ttl, u_char orig_prot, u_long orig_saddr, u_long orig_daddr, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - packet type 2 - packet code 3 - original IP length 4 - original IP TOS 5 - original IP id 6 - original IP fragmentation bits 7 - original IP time to live 8 - original IP protocol 9 - original IP source address 10 - original IP destination address 11 - pointer to original IP payload 12 - original IP payload size 13 - pointer to pre-allocated packet memory

libnet_build_icmp_unreach() constructs an ICMP_UNREACH packet. The 3rd through the 12th arguments are used to build the IP header of the original packet that caused the error message (the ICMP unreachable). The packet type should be ICMP_UNREACH and the code should be one of the following:

VALUE | DESCSRIPTION
ICMP_UNREACH_NET | network is unreachable
ICMP_UNREACH_HOST | host is unreachable
ICMP_UNREACH_PROTOCOL | protocol is unreachable
ICMP_UNREACH_PORT | port is unreachable
ICMP_UNREACH_NEEDFRAG | fragmentation required but DF bit set
ICMP_UNREACH_SRCFAIL | source routing failed
ICMP_UNREACH_NET_UNKOWN | network is unknown
ICMP_UNREACH_HOST_PROHIB | host is prohibited
ICMP_UNREACH_TOSNET | IP TOS and network
ICMP_UNREACH_TOSHOST | IP TOS and host
ICMP_UNREACH_FILTER_PROHIB | prohibitive filtering
ICMP_UNREACH_HOST_PRECEDENCE | host precedence
ICMP_UNREACH_PRECEDENCE_CUTOFF | host precedence cut-off

int libnet_build_icmp_timeexceed(u_char, u_char, u_short, u_char, u_short, u_short, u_char, u_char, u_long, u_long, const u_char *, int, u_char *);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - packet type 2 - packet code 3 - original IP length 4 - original IP TOS 5 - original IP id 6 - original IP fragmentation bits 7 - original IP time to live 8 - original IP protocol 9 - original IP source address 10 - original IP destination address 11 - pointer to original IP payload 12 - original IP payload size 13 - pointer to pre-allocated packet memory

libnet_build_icmp_timeexceed() constructs an ICMP_TIMEXCEED packet. This function is identical to libnet_build_icmp_unreach with the exception of the packet type and code. The packet type should be either ICMP_TIMXCEED_INTRANS for packets that expired in transit (TTL expired) or ICMP_TIMXCEED_REASS for packets that expired in the fragmentation reassembly queue.

int libnet_build_icmp_redirect(u_char type, u_char code, u_long gateway, u_short orig_len, u_char orig_tos, u_short orig_id, u_short orig_frag, u_char orig_ttl, u_char orig_prot, u_long orig_saddr, u_long orig_daddr, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - packet type 2 - packet code 3 - IP address of the gateway 4 - original IP length 5 - original IP TOS 6 - original IP id 7 - original IP fragmentation bits 8 - original IP time to live 9 - original IP protocol 10 - original IP source address 11 - original IP destination address 12 - pointer to original IP payload 13 - original IP payload size 14 - pointer to pre-allocated packet memory

libnet_build_icmp_redirect() constructs an ICMP_REDIRECT packet. This function is similar to libnet_build_icmp_unreach, the differences being the type and code and the addition of an argument to hold the IP address of the gateway that should be used (hence the redirect). The packet type should be ICMP_REDIRECT and the code should be one of the following:

VALUE | DESCSRIPTION
ICMP_UNREACH_NET | redirect for network
ICMP_UNREACH_HOST | redirect for host
ICMP_UNREACH_PROTOCOL | redirect for TOS and network
ICMP_UNREACH_PORT | redirect for TOS and host

int libnet_build_icmp_timestamp(u_char type, u_char code, u_short id, u_short seq, n_time otime, n_time rtime, n_time ttime, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - packet type 2 - packet code 3 - packet id 4 - packet sequence number 5 - originate timestamp 6 - receive timestamp 7 - transmit timestamp 8 - pointer to packet payload 9 - packet payload size 10 - pointer to pre-allocated packet memory

libnet_build_icmp_timestamp() constructs an ICMP_TSTAMP / ICMP_TSTAMPREPLY packet. The packet type should be ICMP_TSTAMP or ICMP_TSTAMPREPLY and the code should be 0.

int libnet_build_igmp(u_char type, u_char code, u_long ip, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - packet type 2 - packet code 3 - IP address 4 - pointer to packet payload 5 - packet payload size 6 - pointer to pre-allocated packet memory

libnet_build_igmp() constructs an IGMP packet. The packet type should be one of the following:

VALUE | DESCSRIPTION
IGMP_MEMBERSHIP_QUERY | membership query
IGMP_V1_MEMBERSHIP_REPORT | version 1 membership report
IGMP_V2_MEMBERSHIP_REPORT | version 2 membership report
IGMP_LEAVE_GROUP | leave-group message

The code, which is a routing sub-message, should probably be left to 0, unless you know what you're doing.

int libnet_build_ip(u_short len, u_char tos, u_short ip_id, u_short frag, u_char ttl, u_char protocol, u_long saddr, u_long daddr, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - packet length (not including the IP header) 2 - type of service 3 - packet id 4 - fragmentation bits / offset 5 - time to live 6 - protocol 7 - source address 8 - destination address 9 - pointer to packet payload 10 - packet payload length 11 - pointer to pre-allocated packet memory

libnet_build_ip() constructs the mighty IP packet. The fragmentation field may be 0 or contain some combination of the following:

VALUE | DESCRIPTION
IP_DF | don't fragment this datagram (only valid when alone)
IP_MF | more fragments on the way (OR'd together with an offset value)

The IP_OFFMASK is used to retrieve the offset from the fragmentation field. IP packets may be no larger than IP_MAXPACKET bytes. The source and destination addresses need to be in network-byte order. The payload interface should only be used to construct an arbitrary or non-supported type IP datagram. To construct a TCP, UDP, or similar type packet, use the relevant libnet_build function.

int libnet_build_ospf(u_short len, u_char type, u_long router_id, u_long area_id, u_short auth_type, const char *payload, int payload_s, u_char *buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - packet length (not including the OSPF header) 2 - packet type 3 - router ID 4 - area ID 5 - authentication type 6 - pointer to packet payload 7 - packet payload length 8 - pointer to pre-allocated packet memory

libnet_build_ospf() builds a OSPF packet. You pass the packet length (not including the OSPF header), the packet type, 32-bit router ID, 32-bit area ID, the authentication type, a pointer to an optional data payload, the payload length, and a pointer to a pre-allocated block of memory for the packet. The payload should not be used to build the Hello, LSA, LSU, LSR, or DBD packets as there are specific construction functions for those packet types. The following variables are to be used for the OSPF packet type:

VALUE | DESCSRIPTION
OSPF_UMD | UMD monitoring packet
OSPF_HELLO | Hello packet
OSPF_DBD | Database description packet
OSPF_LSR | Link state request packet
OSPF_LSU | Link state update packet
OSPF_LSA | Link state acknowledgement packet

The following are the possible authentication types:

VALUE | DESCRIPTION
OSPF_AUTH_NULL | NULL password
OSPF_AUTH_SIMPLE | plaintext, 8 character password
OSPF_AUTH_MD5 | MD5

The following is the structure used for the 64 bit field when using MD5:

`struct auth {`
`u_short ospf_auth_null; /* NULL 16 bits */`
`u_char ospf_auth_keyid; /* Key ID */`
`u_char ospf_auth_len; /* Auth data len */`
`u_int ospf_auth_seq; /* Sequence num */`
`};`

int libnet_build_ospf_hello(u_long netmask, u_short interval, u_char options, u_char priority, u_int dead_interval, u_long des_router, u_long backup, u_long neighbor, const char *payload, int payload_s, u_char *buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - netmask for interface 2 - num of seconds since last packet was sent 3 - options 4 - priority 5 - num of seconds until router is deemed dead 6 - designated router 7 - backup router 8 - neighbor 9 - packet payload 10 - payload length 11 - pointer to pre-allocated packet memory

libnet_build_ospf_hello() builds an OSPF Hello packet. You pass the netmask for the interface, the number of seconds since the last packet was sent, possible options, the router's priority (if 0, it can't be a backup router), the time (in seconds) until a router is deemed down, the networks designated router, the networks backup router, a neighbor, a pointer to an optional data payload, the payload length, and a pointer to a pre-allocated block of memory used for the packet. If there is more than one neighbor that is to be included in the packet, just allocate enough space for the packet buf, and pass the neighbors as the "optional data payload."

int libnet_build_ospf_dbd(u_short len, u_char options, u_char type, u_int sequence_num, const char *payload, int payload_s, u_char *buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - length 2 - options 3 - type 4 - sequence number 5 - packet payload 6 - payload length 7 - pointer to pre-allocated packet memory

libnet_build_ospf_dbd() builds an OSPF DataBase Description (DBD) packet. You pass the maximum length of an IP packet the interface can use, packet options, the type of exchange occurring, a sequence number, a pointer to an optional data payload, the payload length, and a pointer to a pre-allocated block of memory for the packet. The following can be used for the type variable:

VALUE | DESCRIPTION
DBD_IBIT | Initialization bit
DBD_MBIT | More DBD packets en route
DBD_MSBIT | Sender is the master

int libnet_build_ospf_lsr(u_int type, u_int ls_id, u_long adv_router, const char *payload, int payload_s, u_char *buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - type 2 - ID 3 - advertising router 4 - packet payload 5 - payload length 6 - pointer to pre-allocated packet memory

libnet_build_ospf_lsr() builds an OSPF Link State Request (LSR) packet. You pass the type of link state packet being requested, the link state ID, the advertising router, a pointer to an optional data payload, the payload length, and a pointer to a pre-allocated block of memory for the packet. See the libnet_build_ospf_lsa() section for more information regarding variables.

int libnet_build_ospf_lsu(u_int num, const char *payload, int payload_s, u_char *buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - number of LSA packets inside 2 - packet payload 3 - payload length 4 - pointer to pre-allocated packet memory

libnet_build_ospf_lsu() builds an OSPF Link State Update (LSU) packet. You pass the number of Link State Acknowledgment (LSA) packets that will be in the packet, a pointer to an optional data payload, the payload length, and a pointer to a pre-allocated block of memory for the packet.

int libnet_build_ospf_lsa(u_short age, u_char options, u_char type, u_int ls_id, u_long adv_router, u_int sequence_num, u_short len, const char *payload, int payload_s, u_char *buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - link state age 2 - options 3 - type 4 - link state ID 5 - advertising router 6 - sequence number 7 - length not including LSA header 8 - packet payload 9 - payload length 10 - pointer to pre-allocated packet memory

libnet_build_ospf_lsa() builds an OSPF Link State Acknowledgement (LSA) packet. You pass the link state age, packet options, type of LSA, the link state ID, the advertising router, the packet's sequence number, the length of the packet (_not_ including the LSA header length), a pointer to an optional data payload, the payload length, and a pointer to a pre-allocated block of memory for the packet. The following variables can be used for the type of LSA:

VALUE | DESCRIPTION
LS_TYPE_RTR | Router LSA
LS_TYPE_NET | Network LSA
LS_TYPE_IP | Summary LSA (IP network)
LS_TYPE_ASBR | Summary LSA (ASBR)
LS_TYPE_ASEXT | AS-External LSA

int libnet_build_ospf_lsa_rtr(u_short flags, u_short num, u_int id, u_int data, u_char type, u_char tos, u_short metric, const char *payload, int payload_s, u_char *buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - flags 2 - number of links 3 - link ID 4 - info for link ID 5 - router link type 6 - TOS metrics 7 - packet payload 8 - payload length 9 - pointer to pre-allocated packet memory

libnet_build_ospf_lsa_rtr() builds an OSPF Link State Router packet. You pass the optional packet flags, the number of links within that packet, the link ID (helps describe the next variable), the info for the specified link ID, the type of router link, the number of TOS metrics for this link, the metric (the cost of using the link), a pointer to an optional data payload, the payload length, and a pointer to a pre-allocated block of memory for the packet. The possible flags (not including 0x00) are as follows:

VALUE | DESCRIPTION
RTR_FLAGS_W | W bit
RTR_FLAGS_E | E bit
RTR_FLAGS_B | B bit

The possible link ID's are as follows:

VALUE | DESCRIPTION
LINK_ID_NBR_ID | Neighbors router ID
LINK_ID_IP_DES | IP address of router
LINK_ID_SUB | IP subnet number

The possible values for the router type are as follows:

VALUE | DESCRIPTION
RTR_TYPE_PTP | Point to point
RTR_TYPE_TRANS | Connection to a `transit network`
RTR_TYPE_STUB | Connection to a `stub network`
RTR_TYPE_VRTL | Connection to a `virtual link`

int libnet_build_ospf_lsa_net(u_long netmask, u_int router_id, const char *payload, int payload_s, u_char *buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - netmask 2 - router ID 3 - packet payload 4 - packet payload length 5 - pointer to pre-allocated packet memory

libnet_build_ospf_lsa_net() builds an OSPF Link Sate Network packet. You pass the interface's netmask, the router ID, a pointer to an optional data payload, the payload length, and a pointer to a pre-allocated block of memory for the packet.

int libnet_build_ospf_lsa_sum(u_long netmask, u_int metric, u_int tos, const char *payload, int payload_s, u_char *buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - netmask 2 - metric 3 - TOS 4 - packet payload 5 - packet payload length 6 - pointer to pre-allocated packet memory

libnet_build_ospf_lsa_sum() builds an OSPF Link State Summary packet. You pass the interface's netmask, the cost of using the link (metric), the TOS, which is passed as a unsigned integer but the first 8 bits are the TOS and the last 24 bits are the TOS metric, a pointer to an optional data payload, the payload length, and a pointer to a pre-allocated block of memory for the packet.

int libnet_build_ospf_lsa_as(u_long netmask, u_int metric, u_long fwd_addr, u_int tag, const char *payload, int payload_s, u_char *buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - netmask 2 - metric 3 - forwarding address 4 - external route tag 6 - packet payload 7 - packet payload length 8 - pointer to pre-allocated packet memory

libnet_buils_ospf_lsa_as() builds an OSPF Link State AS External packet. You pass the interface's netmask, the cost of using the link (metric), the forwarding address, the external route tag, a pointer to an optional data payload, the payload length, and a pointer to a pre-allocated block of memory for the packet. In reality, the metric only uses the last 24 bits of the unsigned int. The first 8bits are reserved for a possible bit to be set (the E bit, see above for more info). The variable AS_E_BIT_ON can be used logically to set the E bit on.

int libnet_build_rip(u_char cmd, u_char ver, u_short domain, u_short addr_fam, u_short route_tag, u_long ip, u_long mask, u_long next_hop, u_long metric, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - command 2 - version 3 - routing domain (or zero) 4 - address family 5 - route tag (or zero) 6 - IP address 7 - netmask (or zero) 8 - next hop IP address (or zero) 9 - metric 10 - pointer to packet payload 11 - packet payload length 12 - pointer to pre-allocated packet memory

libnet_build_rip() constructs a RIP packet. Depending on the version of RIP you are using, packet fields are slightly different. The following chart highlights these differences:

ARGUMENT | VERSION 1 | VERSION 2
1 | command | command
2 | RIPVER_1 | RIPVER_2
3 | zero | routing domain
4 | address family | address family
5 | zero | subnet mask
6 | IP address | IP address
7 | zero | subnet mask
8 | zero | next hop ip
9 | metric | metric

The RIP commands should be one of the following:

VALUE | DESCRIPTION
RIPCMD_REQUEST | RIP request
RIPCMD_RESPONSE | RIP response
RIPCMD_TRACEON | RIP tracing on
RIPCMD_TRACEOFF | RIP tracing off
RIPCMD_POLL | RIP polling
RIPCMD_POLLENTRY | RIP poll entry
RIPCMD_MAX |

int libnet_build_tcp(u_short th_sport, u_short th_dport, u_long th_seq, u_long th_ack, u_char th_flags, u_short th_win, u_short th_urg, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - source port 2 - destination port 3 - sequence number 4 - acknowledgement number 5 - control flags 6 - window size 7 - urgent pointer 8 - pointer to packet payload 9 - packet payload size 10 - pointer to pre-allocated packet memory

libnet_build_tcp() constructs a TCP packet. The control flags should be one or more of the following (OR'd together if need be):

VALUE | DESCSRIPTION
TH_URG | urgent data is present
TH_ACK | acknowledgement number field should be checked
TH_PSH | push this data to the application
TH_RST | reset the referenced connection
TH_SYN | synchronize connection sequence numbers
TH_FIN | sender is finished sending data

int libnet_build_udp(u_short sport, u_short dport, const u_char *payload, int payload_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - source port 2 - destination port 3 - pointer to packet payload 4 - packet payload size 5 - pointer to pre-allocated packet memory

libnet_build_udp() constructs a UDP packet. Please remember that UDP checksums are considered mandatory by the host requirements RFC.

int libnet_insert_ipo(struct ipoption *opt, u_char opt_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - pointer to a IP options structure (filled in) 2 - options length 3 - pointer to a complete IP packet

libnet_insert_ipo() inserts IP options into a pre-built IP packet. Supplied is a pointer to an ip options structure, the size of this options list, and a pointer the pre-built packet. The options list should be constructed as they will appear on the wire, as they are simply inserted into the packet at the appropriate location.

The function returns -1 if the options would result in packet too large (greater then 65535 bytes), or if the packet buffer is NULL. It is an unchecked runtime error for the user to have not allocated enough heap memory for the IP packet plus the IP options.

int libnet_insert_tcpo(struct tcpoption *opt, u_char opt_len, u_char *packet_buf);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - pointer to a TCP options structure (filled in) 2 - options length 3 - pointer to a complete IP/TCP packet

libnet_insert_tcpo() inserts TCP options into a pre-built IP/TCP packet. Supplied is a pointer to a tcp options structure, the size of this options list, and a pointer the pre-built packet. The options list should be constructed as they will appear on the wire, as they are simply inserted into the packet at the appropriate location.

The function returns -1 if the options would result in packet too large (greater then 65535 bytes), if the packet isn't an IP/TCP packet, if the options list if longer than 20 bytes, or if the packet buffer is NULL. It is an unchecked runtime error for the user to have not allocated enough heap memory for the IP/TCP packet plus the IP options.

5.5 Support Functions

int libnet_seed_prand();

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | NA

libnet_seed_prand() seeds the pseudo-random number generator. The function is basically a wrapper to srandom. It makes a call to gettimeofday to get entropy. It can return -1 if the call to gettimeofday fails (check errno). It otherwise returns 1.

u_long libnet_get_prand(int modulus);

return value upon success | 1
return value upon failure | NA
re-entrant | yes
arguments | 1 - maximum size of pseudo-random number desired

libnet_get_prand() generates a psuedo-random number. The range of the returned number is controlled by the function's only argument:

VALUE | DESCSRIPTION
LIBNET_PR2 | 0 - 1
LIBNET_PR8 | 0 - 255
LIBNET_PR16 | 0 - 32767
LIBNET_PRu16 | 0 - 65535
LIBNET_PR32 | 0 - 2147483647
LIBNET_PRu32 | 0 - 4294967295

The function does not fail.

void libnet_hex_dump(u_char * buf, int len, int swap, FILE *stream);

return value upon success | NA
return value upon failure | NA
re-entrant | yes
arguments | 1 - packet to dump 2 - packet length 3 - byte swap flag 4 - previously opened stream in which to dump packet

libnet_hex_dump() prints out a packet in hexadecimal. It will print the packet as it appears in memory, or as it will appear on the wire, depending on the value of the byte-swap flag. The function prints the packet to a previously opened stream (such as stdout). Note that on big-endian architectures such as Solaris, the packet will appear the same in memory as it will on the wire.

int libnet_plist_chain_new(struct libnet_plist_chain **plist, char *token_list);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - pointer to a libnet_plist_chain pointer 2 - pointer to token list

libnet_plist_chain_new() constructs a new libnet port-list chain. A libnet port-list chain is a fast and simple way of implementing port-list ranges (useful for applications that employ a list of ports - like a port scanner). You'll see naive implementations that allocate an entire array of 65535 bytes and fill in the desired ports one by one. However, we only really need to store the beginning port and the ending port, and we can efficiently store multiple port ranges (delimited by commas) by using a linked list chain with each node holding the beginning and ending port for a particular range. For example, The port range `1-1024` would occupy one node with the beginning port being 1 and the ending port being 1024. The port range `25,110-161,6000` would result in 3 nodes being allocated. Single ports are taken as single ranges (port 25 ends up being 25-25). A port list range without a terminating port (port_num - ) is considered shorthand for (port_num - 65535).

The arguments are a pointer to libnet_plist_chain pointer (which will end up being the head of the linked list) which needs to deference an allocated libnet_plist_chain structure and pointer to the port-list (token-list) itself.

The function checks this character port list for valid tokens (1234567890,- ) and returns an error if an unrecognized token is found.

Upon success the function returns 1, and head points to the newly formed port-list (and also contains the number of nodes in the list. If an error occurs (an unrecognized token is found or malloc fails) -1 is returned and head is set to NULL.

libnet_plist_chain_next_pair() should be used to extract port list pairs.

int libnet_plist_chain_next_pair(struct libnet_plist_chain *plist, u_short *bport, u_short *eport);

return value upon success | 1, 0
return value upon failure | -1
re-entrant | yes
arguments | 1 - pointer to a libnet_plist_chain pointer 2 - pointer to the beginning port (to be filled in) 3 - pointer to the ending port (to be filled in)

libnet_plist_chain_next_pair() fetches the next pair of ports from the list. The function takes a pointer to the head of the prebuilt list and a pointer to a u_short that will contain the beginning port and a pointer to a u_short that will contain the ending port.

The function returns 1 and fills in these values if there are nodes remaining, or if the port list chain is exhausted, it returns 0. If an error occurs (the libnet_plist_chain pointer is NULL) the function
returns -1.

int libnet_plist_chain_dump(struct libnet_plist_chain *plist);

return value upon success | 1
return value upon failure | -1
re-entrant | yes
arguments | 1 - pointer to a libnet_plist_chain pointer

libnet_plist_chain_dump() dumps the port-list chain referenced by the argument. The function prints the list to stdout (it's mainly meant as a debugging tool). It returns 1 upon success or if an error occurs (the libnet_plist_chain pointer is NULL) the function returns -1.

u_char *libnet_plist_chain_dump_string(struct libnet_plist_chain *plist);

return value upon success | pointer to the token list
return value upon failure | NULL
re-entrant | no
arguments | 1 - pointer to a libnet_plist_chain pointer

libnet_plist_chain_dump_string() returns the port-list chain referenced by the argument as a string. It returns the port list string upon success or if an error occurs (the libnet_plist_chain pointer is NULL) the function returns NULL.

void libnet_plist_chain_free(struct libnet_plist_chain *plist);

return value upon success | NA
return value upon failure | NA
re-entrant | yes
arguments | 1 - pointer to a libnet_plist_chain pointer

libnet_plist_chain_free() frees the memory associated with the libnet port list chain.

5.6 Symbolic Constants

Libnet conveniently defines standard packet header sizes, for use with many packet manipulation functions, as per the following chart:

SYMBOLIC CONSTANT | SIZE IN BYTES
LIBNET_ARP_H | 28
LIBNET_DNS_H | 12
LIBNET_ETH_H | 14
LIBNET_ICMP_H (deprecated) | 4
LIBNET_ICMP_ECHO_H | 8
LIBNET_ICMP_MASK_H | 12
LIBNET_ICMP_UNREACH_H | 8
LIBNET_ICMP_TIMXCEED_H | 8
LIBNET_ICMP_REDIRECT_H | 8
LIBNET_ICMP_TS_H | 20
LIBNET_IGMP_H | 8
LIBNET_IP_H | 20
LIBNET_RIP_H | 24
LIBNET_TCP_H | 20
LIBNET_UDP_H | 8

More packet memory constants:

SYMBOLIC CONSTANT | MEANING
LIBNET_PACKET | enough memory for a TCP or UDP header and an IP header
LIBNET_OPTS | enough memory for IP or TCP options (40 bytes)
LIBNET_MAX_PACKET | enough memory for IP_MAXPACKET (65535 bytes)

The following are used for psuedo random number generation, with libnet_get_prand():

SYMBOLIC CONSTANT | RANGE
LIBNET_PRAND_MAX | 65535
LIBNET_PR2 | 0 - 2
LIBNET_PR8 | 0 - 255
LIBNET_PR16 | 0 - 32767
LIBNET_PRu16 | 0 - 65535
LIBNET_PR32 | 0 - 2147483647
LIBNET_PRu32 | 0 - 4294967295

For error messaging, used in conjunction with libnet_error():

SYMBOLIC CONSTANT | MEANING
LIBNET_ERR_WARNING | warning error message
LIBNET_ERR_CRITICAL | critical error message
LIBNET_ERR_FATAL | fatal error message (program will exit)

For use with libnet_host_lookup(), libnet_host_lookup_r(), and libnet_name_resolve():

SYMBOLIC CONSTANT | MEANING
LIBNET_DONT_RESOLVE | do not resolve IP addresses into FQDNs
LIBNET_RESOLVE | attempt to resolve IP addresses into FQDNs

5.7 Macros

The arena interface defines the following macros:

MACRO | MEANING
LIBNET_GET_ARENA_SIZE(`arena`) | returns the size of the arena
LIBNET_GET_ARENA_REMAINING_BYTES(`arena`) | returns the number of bytes left in the arena

To print the ethernet address from an ether_addr struct use the following macro:

MACRO | MEANING
LIBNET_PRINT_ETH_ADDR(`e`) | Prints the ethernet address of the ether_addr struct

Next Previous Top