随机数种子生成器:
int libnet_seed_prand(libnet_t *l);
获取随机数:
u_int32_t libnet_get_prand(int mod);
端口列表链初始化:
int libnet_plist_chain_new(libnet_t *l, libnet_plist_t **plist, char *token_list);
获取端口列表链的下一项(端口范围):
int libnet_plist_chain_next_pair(libnet_plist_t *plist, u_int16_t *bport,
u_int16_t *eport);
端口列表链输出显示:
int libnet_plist_chain_dump(libnet_plist_t *plist);
获取端口列表链:
char *libnet_plist_chain_dump_string(libnet_plist_t *plist);
端口列表链内存释放:
int libnet_plist_chain_free(libnet_plist_t *plist);
对它的使用也非常简单,只要你了解自己要做什么事情、应该把哪些参数放在什么位置。利用libnet函数库开发应用程序的基本步骤非常简单:
1、数据包内存初始化;
2、构造数据包;
3、发送数据;
4、释放资源;
例: libnet的发行包里提供了很多示例程序,其中/libnet/sample/tcp1.c如果省略掉一些参数的设置和错误处理,则程序简化为:
#if (H***E_CONFIG_H)
#i nclude \
#endif
#i nclude \
#ifdef __WIN32__
#i nclude \
#endif
int
main(int argc, char *argv[])
{
//…….
l = libnet_init(
LIBNET_LINK, /* injection type */
NULL, /* network interface */
errbuf); /* error buffer */
//……
t = libnet_build_tcp_options(
\000\
20,
l,
0);
//……
t = libnet_build_tcp(src_prt, dst_prt, 0x01010101, 0x02020202, TH_SYN, 32767, 0, 10,
LIBNET_TCP_H + 20 + payload_s, payload, payload_s, l, 0);
t = libnet_build_ipv4(LIBNET_IPV4_H + LIBNET_TCP_H + 20 + payload_s, 0, 242, 0, 64,
IPPROTO_TCP, 0, src_ip, dst_ip, NULL, 0, l, 0);
t = libnet_build_ethernet(enet_dst, enet_src, ETHERTYPE_IP, NULL, 0, l, 0);
c = libnet_write(l);
libnet_destroy(l);
return (EXIT_SUCCESS);
bad:
libnet_destroy(l);
return (EXIT_FAILURE);
}
#if defined(__WIN32__)
#i nclude <../include/win32/getopt.h>
#i nclude
#i nclude
#endif /* __WIN32__ */
/* EOF */
对libnet源码的分析
★ 整体设计思想
对每个要发送的包,libnet维护一个libnet?_t结构,这个结构是理解整个libnet的关键,也是libnet得以实现它强大功能的关键。让我们先从它入手,从整体到细节地揭开libnet的面纱。下面左图是libnet_t这个结构的示例。
其中的fd就是发送数据包将要用到的socket套接字,injection_type将会被设置成libnet_init()中的第一个参数,即你选择发送的方式,是基于link_layer的链路层数据包?还是基于IP层的raw数据包?后一种情况又分为IP4和IP6两种。protocol_blocks 和protocol_end都是指针,指向一个libnet
自定义的libnet_pblock_t结构,由此管理一个libnet_pblock_t的链表。而libnet_pblock_t则表述各个协议,维护各个协议给发送的数据包添加的数据块,它的具体选项下面再说。link_type表示链路层的类型,link_offset则指向链路层也就是最底层协议包头的偏移地址。aligner是为了维护最后的数据包的字对齐而设置的,字符串指针device则指向通讯所用的设备,比如eth0.state是一个结构,与ptag_state一起,记录包在建立过程中的一些信息。label是一个字符数组。每当有错误发生的时候,errbuf数组就被用来记录错误信息。全部的数据包长度和保存于total_size中。
从libnet_t已经大概可以看出libnet的设计思想了:程序员决定一些参数,并且通过函数调用中的参数把相关的数据交给libnet.libnet则在程序员每要求购建一个协议包头的时候,为其创建一个
libnet_pblock_t的结构保存这些数据,并将该结构入链表。当所有的准备工作完成,程序员一声令下,libnet就将协议块链(由protocol_blocks开始,终于pblock_end)中的协议包头以及数据组合成一个合乎规格的包,通过硬件发送出去。如果任何一个步骤出了差错,程序员都可以从errbuf中获取出错信息。最后,libnet从程序员手中接过一个指令,进行所有的善后工作。
每种协议的包头将在前期被实现为一个libnet_pblock_t的结构。libnet为它所支持的协议都定义了相应的数据结构,例如TCP包头的定义:
struct libnet_tcp_hdr
{
u_int16_t th_sport; /* source port */
u_int16_t th_dport; /* destination port */
u_int32_t th_seq; /* sequence number */
u_int32_t th_ack; /* acknowledgement number */
#if (LIBNET_LIL_ENDIAN)