SrcMAC, /* source MAC addr */ (u_char *)&SrcIP, /* src proto addr */ DstMAC, /* dst MAC addr */ (u_char *)&DstIP, /* dst IP addr */ NULL, /* no payload */ 0, /* payload length */ plibnet_app, /* libnet tag */ 0); /* ptag see man */ /*出错处理*/
if (-1==ptag) /* 把-1写在前面是怕我们粗心的写成 ptag=-1 */ {
perror(\
exit(1); }
/*出错处理*/
以上代码基本上只注意其中的几个参数就可以了:
ARPOP_REPLY 这个参数是个宏也可以是 ARP_REQUEST;表明是ARP查询还是应达。
SrcMAC 指向源MAC数组的指针 DesMAC 指向目地MAC数组的指针 SrcIP 指向源IP地址的指针
DstIP 指向目地IP地直的指针
plibnet_app 刚才我们初始化libnet返回的指针
接下来。我们构造这个ARP包的底层,也就是物理层的数据。一般是ethernet层的ethernet 头数据包。用函数libnet_build_ethernet( );
这个函数很简单同上。也返回一个 libnet_ptag_t的值。如果是-1,说明失败。 libnet_ptag_t eth_tag;
eth_tag = libnet_build_ethernet(
DstMAC, /* dst MAC addr */ SrcMAC, /* src MAC addr */ 0x0806, /* ether packet type */ NULL, /* ptr to payload */ 0, /* payload size */ plibnet_app,
0); /* ptr to packet memory */ /*出错处理*/ if (-1 == eth_tag)
{
perror(\ exit(1);
}
/*出错处理*/
同样只注意 DstMAC ,SrcMAC , plibnet_app三个数据就可以了。 6、发送数据包。一般用一个无限的循环 如:
int n;/*n==-1时没有发送成功*/ for(;;) {
n= libnet_write(plibnet_app); /*出错处理*/
if(-1==n)printf(\ /*出错处理*/ };
7、释放内存。
libnet_destroy(plibnet_app); 三、编译
gcc 源文件.c -o 目标文件 -lnet
四、回顾一下上面的知识。写一个小程序。(注意,这里没有错误检查,为的是让代码更短小)
#include
{
char device[ ]=\ u_int32_t srcip, desip;
u_char srcmac[6]={0x11,0x11,0x11,0x11,0x11,0x11}; u_char desmac[6]={0x22,0x22,0x22,0x22,0x22,0x22};
libnet_t *plibnet_app; char errbuf[100];
plibnet_app=libnet_init(LIBNET_LINK_ADV, device, errbuf);
/******************************************************************************** 下面填充要构造的数据包的内容
要源IP地址:192.168.18.10 MAC地址:11:11:11:11:11:11 目标IP地址:192.168.18.1 MAC地址:22:22:22:22:22:22 源IP向目地IP发送应答包。应答192.168.18.10的MAC地址为11:11:11:11:11:11 **********************************************************************************/
srcip=inet_addr(\ desip=inet_addr(\
/*************************** 以下开始构造ARP包 及ETHERNET包头 **************************************/
libnet_build_arp( ARPHRD_ETHER,//hardware addr ETHERTYPE_IP,//protocol addr 6,//hardware addr size 4,//protocol addr size
ARPOP_REPLY,//operation type
(u_int8_t*)&srcmac,//sender hardware addr (u_int8_t point) (u_int8_t *)&srcip,//sender protocol addr(u_int8_t point) (u_int8_t*)&desmac,//target hardware addr(u_int8_t point)
(u_int8_t *)&desip,//target protocol addr(u_int8_t point) NULL,//payload 0,//payload size
plibnet_app,//libnet handle 0/*libnet id*/);
libnet_build_ethernet( desmac,//des HW addr* srcmac,//src HW addr* 0x0806,//ether packet type NULL,//prt to payload 0,//payload size
plibnet_app,//libnet handle 0);//ptr toi packet memory
/********************************** 构造完成。开始发包 **************************************/ for(;;) {
//libnet_adv_cull_packet(plibnet_app, &packet, &packet_size); libnet_write(plibnet_app); printf(\ sleep(1);
};
/***********************************
********************************************/ libnet_destroy(plibnet_app); return 0;
}
/***********************************UBUNTU7.10, libnet1.13RC01下调试通过********************************************* gcc test.c -o test -lnet ./test
产生的数据,用Wireshark抓包得到如下结果
0000 22 22 22 22 22 22 11 11 11 11 11 11 08 06 00 01 \ 0010 08 00 06 04 00 02 11 11 11 11 11 11 c0 a8 12 0a ........ ........ 0020 22 22 22 22 22 22 c0 a8 12 01 \
************************************注意你的网卡一般是eht0。我的网卡名是eth1********************************************/
结
束
Linux网络编程学习之libnet的介绍与分析
星期四, 02/28/2013 - 17:02 — sunplusedu2012
libnet是UNIX系统同台上网络安全工具开发的重要的库,它和libpcap、libnids一起,给网络安全工具的开发人员提供了一组丰富而且完全的武器,使之得以很方便地编写出结构化强、健壮性好、可移植性高等特点的程序。
libnet提供一系列的接口函数,实现和封装了数据包的构造和发送过程。利用它可以亲自构造从应用层到链路层的各层协议的数据包头,并将这些包头与有效数据有序地组合在一起发送出去。当然,它也是基于tcp/ip协议族模型的。
libnet当前的版本是1.1.2,相对于1.0.*版本有比较大的变化。
全部源代码包括18,000 行代码,109个导出函数,其中包括67个建包函数。这使得它支持现有的TCP/IP族的所有协议。此外,它支持多平台,Windows,OS X,BSD,Linux, Solaris,HPUX都能使用。
下图是它支持的协议:
libnet库可以被划分为4个功能部分:内存管理、地址解析、包处理、以及其他一些支持函数。
★ 内存管理函数
单数据包内存初始化及环境建立:
libnet_t *libnet_init(int injection_type, char *device, char *err_buf);
资源释放:
void libnet_destroy(libnet_t *l);
★ 地址解析函数
地址解析:
char *libnet_addr2name4(u_int32_t in, u_int8_t use_name);
libnet_name2addr4(libnet_t *l, char *host_name, u_int8_t use_name);
struct libnet_in6_addr libnet_name2addr6(libnet_t *l, char *host_name, u_int8_t use_name);
void libnet_addr2name6_r(struct libnet_in6_addr addr, u_int8_t use_name,
char *host_name, int host_name_len);
获取接口设备IP地址:
u_int32_t libnet_get_ipaddr4(libnet_t *l);
struct libnet_in6_addr libnet_get_ipaddr6(libnet_t *l);
获取接口设备硬件地址:
struct libnet_ether_addr *libnet_get_hwaddr(libnet_t *l);
★ 数据包构造函数
(这一部分函数较多,都以libnet_build_*()的形式出现,在此略过)
★ 数据包发送函数
int libnet_write(libnet_t *l);
★ 相关的支持函数