首页 / 操作系统 / Linux / Linux 网络编程—— libnet 使用指南
概述通过《原始套接字实例:发送 UDP 数据包》的学习,我们组 UDP 数据包时常考虑字节流顺序、校验和计算等问题,有时候会比较繁琐,那么,有没有一种更简单的方法呢?答案是:借助 libnet 函数库。libnet 是一个小型的接口函数库,主要用 C 语言写成,提供了低层网络数据包的构造、处理和发送功能。libnet 的开发目的是:建立一个简单统一的网络编程接口以屏蔽不同操作系统底层网络编程的差别,使得程序员将精力集中在解决关键问题上。libnet 库提供的接口函数包含 15 种数据包生成器和两种数据包发送器(IP 层和数据链路层)。源代码下载:------------------------------------------分割线------------------------------------------免费下载地址在 http://linux.linuxidc.com/用户名与密码都是www.linuxidc.com具体下载目录在 /2015年资料/4月/13日/Linux 网络编程—— libnet 使用指南/下载方法见 http://www.linuxidc.com/Linux/2013-07/87684.htm------------------------------------------分割线------------------------------------------提供的接口函数包括:1)内存管理(分配和释放)函数2)地址解析函数3)各种协议类型的数据包构造函数4)数据包发送函数(IP层和链路层)5)一些辅助函数,如产生随机数、错误报告、端口列表管理等详情请看《libnet 函数列表》http://www.linuxidc.com/Linux/2015-04/116152.htm。libnet 的安装流程利用libnet函数库开发应用程序的基本步骤:1)数据包内存初始化2)构造数据包3)发送数据4)释放资源以发送 UDP 数据包为例,流程图如下:这里需要注意的是组包的顺序,由上层再到底层,这里为 udp -> ip -> mac,不能反过来。常用函数介绍以下函数的使用需要包含头文件 libnet.hlibnet_t *libnet_init(int injection_type, char *device, char *err_buf)功能:数据包内存初始化及环境建立参数:injection_type:构造的类型LIBNET_LINK,链路层LIBNET_RAW4,网络接口层(网络层)LIBNET_LINK_ADV,链路层高级版本LIBNET_RAW4_ADV, 网络层高级版本device:网络接口,如 "eth0",或 IP 地址,亦可为 NULL (自动查询搜索)err_buf:存放出错的信息返回值:成功:一个 libnet * 类型的指针,后面的操作都得使用这个指针失败:NULLvoid libnet_destroy(libnet_t *l);功能:释放资源参数:l:libnet_init() 返回的 libnet * 指针返回值:无char* libnet_addr2name4(u_int32_t in, u_int8_t use_name)功能:将网络字节序转换成点分十进制数串参数:in:网络字节序的 ip 地址use_name:LIBNET_RESOLVE, 对应主机名LIBNET_DONT_RESOLVE,对应点分十进制 IPv4 地址返回值:成功:点分十进制 ip 地址失败:NULLu_int32_t libnet_name2addr4(libnet_t *l,char *host_name,u_int8_t use_name)功能:将点分十进制数串转换为网络字节序 ip 地址参数:l:libnet_init() 返回的 libnet * 指针host_name:LIBNET_RESOLVE, 对应主机名LIBNET_DONT_RESOLVE,对应点分十进制 IPv4 地址返回值:成功:网络字节序 ip 地址失败:-1u_int32_t libnet_get_ipaddr4(libnet_t *l)功能:获取接口设备 ip 地址参数:l:libnet_init() 返回的 libnet * 指针返回值:成功:网络字节序的 ip 地址失败:-1struct libnet_ether_addr* libnet_get_hwaddr(libnet_t *l)功能:获取接口设备硬件地址参数:l:libnet_init() 返回的 libnet * 指针返回值:成功:指向 MAC 地址的指针失败:NULLlibnet_ptag_t libnet_build_udp(u_int16_t sp, u_int16_t dp,u_int16_t len, u_int16_t sum,u_int8_t *payload, u_int32_t payload_s,libnet_t *l, libnet_ptag_t ptag)功能:构造 udp 数据包参数:sp: 源端口号dp:目的端口号len:udp 包总长度sum:校验和,设为 0,libnet 自动填充payload:负载,为给应用程序发送的文本内容,没有内容时可设置为 NULLpayload_s:负载长度,给应用程序发送文本内容的长度,或为 0l:libnet_init() 返回的 libnet * 指针ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。返回值:成功:协议标记失败:-1libnet_ptag_t libnet_build_tcp(u_int16_t sp, u_int16_t dp,u_int32_t seq, u_int32_t ack,u_int8_t control, u_int16_t winu_int16_t sum, u_int16_t urg,u_int16_t len, u_int8_t *payload,u_int32_t payload_s, libnet_t *l,libnet_ptag_t ptag )功能:构造 tcp 数据包参数:sp:源端口号dp:目的端口号seq:序号ack:ack 标记control:控制标记win:窗口大小sum:校验和,设为 0,libnet 自动填充urg:紧急指针len:tcp包长度payload:负载,为给应用程序发送的文本内容,可设置为 NULLpayload_s:负载长度,或为 0l:libnet_init() 返回的 libnet * 指针ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。返回值:成功:协议标记失败:-1libnet_ptag_t libnet_build_tcp_options(u_int8_t *options,u_int32_t options_s,libnet_t *l,libnet_ptag_t ptag )功能:构造 tcp 选项数据包参数:options:tcp 选项字符串options_s:选项长度l:libnet 句柄,libnet_init() 返回的 libnet * 指针ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。返回值:成功:协议标记失败:-1libnet_ptag_t libnet_build_ipv4(u_int16_t ip_len, u_int8_t tos,u_int16_t id, u_int16_t flag,u_int8_t ttl, u_int8_t prot,u_int16 sum, u_int32_t src,u_int32_t dst, u_int8_t *payload,u_int32_t payload_s,libnet_t *l,libnet_ptag_t ptag )功能:构造一个 IPv4 数据包参数:ip_len:ip 包总长tos:服务类型id:ip 标识flag:片偏移ttl:生存时间prot:上层协议sum:校验和,设为 0,libnet 自动填充src:源 ip 地址dst:目的ip地址payload:负载,可设置为 NULL(这里通常写 NULL)payload_s:负载长度,或为 0(这里通常写 0 )l:libnet 句柄,libnet_init() 返回的 libnet * 指针ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。返回值:成功:协议标记失败:-1libnet_ptag_t libnet_build_ipv4_options(u_int8_t*options, u_int32_t options,libnet_t*l, libnet_ptag_t ptag)功能:构造 IPv4 选项数据包参数:options:tcp 选项字符串options_s:选项长度l:libnet 句柄,libnet_init() 返回的 libnet * 指针ptag:协议标记,若为 0,建立一个新的协议返回值:成功:协议标记失败:-1libnet_ptag_t libnet_build_arp(u_int16_t hrd, u_int16_t pro,u_int8_t hln, u_int8_t pln,u_int16_t op, u_int8_t *sha,u_int8_t *spa, u_int8_t *tha,u_int8_t *tpa, u_int8_t *payload,u_int32_t payload_s, libnet_t *l,libnet_ptag_t ptag )功能:构造 arp 数据包参数:hrd:硬件地址格式,ARPHRD_ETHER(以太网)pro:协议地址格式,ETHERTYPE_IP( IP协议)hln:硬件地址长度pln:协议地址长度op:ARP协议操作类型(1:ARP请求,2:ARP回应,3:RARP请求,4:RARP回应)sha:发送者硬件地址spa:发送者协议地址tha:目标硬件地址tpa:目标协议地址payload:负载,可设置为 NULL(这里通常写 NULL)payload_s:负载长度,或为 0(这里通常写 0 )l:libnet 句柄,libnet_init() 返回的 libnet * 指针ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。返回值:成功:协议标记失败:-1libnet_ptag_t libnet_build_ethernet(u_int8_t*dst, u_int8_t *src,u_int16_ttype, u_int8_t*payload,u_int32_tpayload_s, libnet_t*l,libnet_ptag_t ptag )功能:构造一个以太网数据包参数:dst:目的 macsrc:源 mactype:上层协议类型payload:负载,即附带的数据,可设置为 NULL(这里通常写 NULL)payload_s:负载长度,或为 0(这里通常写 0 )l:libnet 句柄,libnet_init() 返回的 libnet * 指针ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。返回值:成功:协议标记失败:-1int libnet_write(libnet_t * l)功能:发送数据包参数:l:libnet 句柄,libnet_init() 返回的 libnet * 指针返回值:成功:发送数据包的长度失败:返回 -1更多详情见请继续阅读下一页的精彩内容: http://www.linuxidc.com/Linux/2015-04/116151p2.htm