常用函数
libnet_init()
作用
数据包内存初始化及环境建立
函数原型
libnet_t *libnet_init(int injection_type, char *device, char *err_buf);
返回值
成功:一个 libnet * 类型的指针,后面的操作都得使用这个指针
失败:NULL
参数详解
- injection_type:构造的类型
LIBNET_LINK,链路层
LIBNET_RAW4,网络接口层(网络层)
LIBNET_LINK_ADV,链路层高级版本
LIBNET_RAW4_ADV, 网络层高级版本 - device:网络接口,如 "eth0",或 IP 地址,亦可为 NULL (自动查询搜索)
- err_buf:存放出错的信息
C语言代码示例
//无
libnet_destroy()
作用
释放资源
函数原型
void libnet_destroy(libnet_t *l);
返回值
无
参数详解
- l:libnet_init() 返回的 libnet * 指针
C语言代码示例
//无
libnet_addr2name4()
作用
将网络字节序转换成点分十进制数串
函数原型
char* libnet_addr2name4(u_int32_t in, u_int8_t use_name);
返回值
成功:点分十进制 ip 地址
失败:NULL
参数详解
- in:网络字节序的 ip 地址
- use_name:
LIBNET_RESOLVE, 对应主机名。
LIBNET_DONT_RESOLVE,对应点分十进制 IPv4 地址。
一般都指定该函数的第二个参数为LIBNET_RESOLVE。
C语言代码示例
//无
libnet_name2addr4()
作用
将点分十进制数串转换为网络字节序 ip 地址
函数原型
u_int32_t libnet_name2addr4(libnet_t *l, char *host_name, u_int8_t use_name);
返回值
成功:网络字节序 ip 地址
失败:-1
参数详解
- l:libnet_init() 返回的 libnet * 指针
- host_name:点分十进制的IP字符串
- use_name:
LIBNET_RESOLVE, 对应主机名。
LIBNET_DONT_RESOLVE,对应点分十进制 IPv4 地址。
一般都指定该函数的第二个参数为LIBNET_RESOLVE。
C语言代码示例
//无
libnet_get_ipaddr4()
作用
获取接口设备 ip 地址
函数原型
u_int32_t libnet_get_ipaddr4(libnet_t *l);
返回值
成功:网络字节序的 ip 地址
失败:-1
参数详解
- l:libnet_init() 返回的 libnet * 指针
C语言代码示例
//无
libnet_get_hwaddr()
作用
获取接口设备硬件地址
函数原型
struct libnet_ether_addr* libnet_get_hwaddr(libnet_t *l);
返回值
成功:指向 MAC 地址的指针
失败:NULL
参数详解
- l:libnet_init() 返回的 libnet * 指针
C语言代码示例
//无
libnet_build_udp()
作用
构造 udp 数据包
函数原型
libnet_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);
返回值
成功:协议标记
失败:-1
参数详解
- sp: 源端口号
- dp:目的端口号
- len:udp 包总长度
- sum:校验和,设为 0,libnet 自动填充
- payload:负载,为给应用程序发送的文本内容,没有内容时可设置为 NULL
- payload_s:负载长度,给应用程序发送文本内容的长度,或为 0
- l:libnet_init() 返回的 libnet * 指针
- ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。
C语言代码示例
//无
libnet_build_tcp()
作用
构造 tcp 数据包
函数原型
libnet_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 win, u_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);
返回值
成功:协议标记
失败:-1
参数详解
- sp:源端口号
- dp:目的端口号
- seq:序号
- ack:ack 标记
- control:控制标记
- win:窗口大小
- sum:校验和,设为 0,libnet 自动填充
- urg:紧急指针
- len:tcp包长度
- payload:负载,为给应用程序发送的文本内容,可设置为 NULL
- payload_s:负载长度,或为 0
- l:libnet_init() 返回的 libnet * 指针
- ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。
C语言代码示例
//无
libnet_build_tcp_options()
作用
构造 tcp 选项数据包
函数原型
libnet_ptag_t libnet_build_tcp_options(u_int8_t *options, u_int32_t options_s, libnet_t *l, libnet_ptag_t ptag);
返回值
成功:协议标记
失败:-1
参数详解
- options:tcp 选项字符串
- options_s:选项长度
- l:libnet 句柄,libnet_init() 返回的 libnet * 指针
- ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。
C语言代码示例
//无
libnet_build_ipv4()
作用
构造一个 IPv4 数据包
函数原型
libnet_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);
返回值
成功:协议标记
失败:-1
参数详解
- 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,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。
C语言代码示例
//无
libnet_build_ipv4_options()
作用
构造 IPv4 选项数据包
函数原型
libnet_ptag_t libnet_build_ipv4_options(u_int8_t*options, u_int32_t options, libnet_t*l, libnet_ptag_t ptag);
返回值
成功:协议标记
失败:-1
参数详解
- options:tcp 选项字符串
- options_s:选项长度
- l:libnet 句柄,libnet_init() 返回的 libnet * 指针
- ptag:协议标记,若为 0,建立一个新的协议
C语言代码示例
//无
libnet_build_arp()
作用
构造 arp 数据包
函数原型
libnet_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);
返回值
成功:协议标记
失败:-1
参数详解
- 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,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。
C语言代码示例
//无
libnet_build_ethernet()
作用
构造一个以太网数据包
函数原型
libnet_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);
返回值
成功:协议标记
失败:-1
参数详解
- dst:目的 mac
- src:源 mac
- type:上层协议类型
- payload:负载,即附带的数据,可设置为 NULL(这里通常写 NULL)
- payload_s:负载长度,或为 0(这里通常写 0 )
- l:libnet 句柄,libnet_init() 返回的 libnet * 指针
- ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。
C语言代码示例
//无
libnet_write();
作用
发送数据包
函数原型
int libnet_write(libnet_t * l);
返回值
成功:发送数据包的长度
失败:返回 -1
参数详解
- l:libnet 句柄,libnet_init() 返回的 libnet * 指针
C语言代码示例
//无
综合例子
C语言代码
发送数据
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libnet.h>
int main(int argc, char *argv[]){
int res = 0;
char send_msg[1000] = "";
char err_buf[100] = "";
libnet_t *lib_net = NULL;
int lens = 0;
libnet_ptag_t lib_t = 0;
unsigned char src_mac[6] = {0x00,0x0c,0x29,0x86,0x24,0xf8}; //发送者网卡地址00:0c:29:86:24:f8
unsigned char dst_mac[6] = {0x00,0x0c,0x29,0x86,0x24,0xf8}; //接收者网卡地址00:0c:29:86:24:f8
char *src_ip_str = "192.168.8.23"; //源主机IP地址
char *dst_ip_str = "192.168.8.23"; //目的主机IP地址
unsigned long src_ip, dst_ip = 0;
lens = sprintf(send_msg, "%s", "this is for the udp test!");
//初始化
lib_net = libnet_init(LIBNET_LINK_ADV, "ens33", err_buf);
if(lib_net == NULL){
perror("libnet_init error!");
return -1;
}
//将字符串类型的ip转换为顺序网络字节流
src_ip = libnet_name2addr4(lib_net,src_ip_str,LIBNET_RESOLVE);
dst_ip = libnet_name2addr4(lib_net,dst_ip_str,LIBNET_RESOLVE);
//构造udp数据包
lib_t = libnet_build_udp(8080, 8080, 8+lens, 0, send_msg, lens, lib_net, 0);
//构造ip数据包
lib_t = libnet_build_ipv4(20+8+lens, 0, 500, 0, 10, 17, 0, src_ip, dst_ip, NULL, 0, lib_net, 0);
//构造以太网数据包
//0x800 或者,ETHERTYPE_IP
lib_t = libnet_build_ethernet((u_int8_t *)dst_mac, (u_int8_t *)src_mac, 0x800, NULL, 0, lib_net, 0);
//发送数据包
res = libnet_write(lib_net);
if(res == -1){
perror("libnet_write");
return -1;
}
//销毁资源
libnet_destroy(lib_net);
printf("----ok-----\n");
return 0;
}
接收数据
#include <pcap.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <net/ethernet.h>
/* 以太网头总是正好14个字节 */
#define SIZE_ETHERNET 14
/* UDP头总是正好8个字节 */
#define SIZE_UDP 8
void getPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet){
struct ethernet *ethernet; // 以太网头
struct ip *ip; // IP协议头
struct tcphdr *tcp; // TCP协议头
struct udphdr *udp; // UDP协议头
char *payload; // 数据
u_int size_ip;
//u_int size_tcp;
//ethernet = (struct ethernet*)(packet);
ip = (struct ip*)(packet + SIZE_ETHERNET);
size_ip = (ip->ip_hl)*4;
if (size_ip < 20) {
printf("* Invalid IP header length: %u bytes\n", size_ip);
return;
}
//udp = (struct udphdr*)(packet + SIZE_ETHERNET + size_ip);
payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + SIZE_UDP);
printf("message:%s\n", payload);
}
int main(){
char errBuf[PCAP_ERRBUF_SIZE];
char *dev;
pcap_t * handle;
struct bpf_program filter;
int id = 0;
dev = pcap_lookupdev(errBuf);
if(dev){
printf("success: device: %s\n", dev);
}
else{
printf("error: %s\n", errBuf);
return 1;
}
handle = pcap_open_live(dev, 65535, 1, 0, errBuf);
if(!handle){
printf("error: pcap_open_live(): %s\n", errBuf);
exit(1);
}
pcap_compile(handle, &filter, "src host 192.168.8.23 and port 8080", 1, 0);
pcap_setfilter(handle, &filter);
pcap_loop(handle, -1, getPacket, (u_char*)&id);
pcap_close(handle);
return 0;
}