libpcap库用于网络数据分析
This commit is contained in:
parent
08c65c47cb
commit
1f079cfddd
|
@ -0,0 +1,42 @@
|
||||||
|
// libpcap 开发
|
||||||
|
/*
|
||||||
|
libpcap是一个用于捕获网络数据包的库,它提供了一组函数和工具,用于在计算机网络上进行数据包捕获、过滤和分析。
|
||||||
|
在使用libpcap时,你需要在编译和链接你的程序时指定-lpcap选项,以告诉编译器和链接器使用libpcap库。这个选项通常用于Unix-like系统的编译环境,例如在使用GCC编译器时。
|
||||||
|
*/
|
||||||
|
#include <pcap.h> // libpcap头文件
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h> // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 1. 获取可用的网络设备名称
|
||||||
|
char err_buf[PCAP_ERRBUF_SIZE]; // 错误信息缓冲区
|
||||||
|
char *dev = pcap_lookupdev(err_buf); // 获取网络设备名称: err_buf用于存储错误信息
|
||||||
|
// char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备
|
||||||
|
if (dev != NULL)
|
||||||
|
{
|
||||||
|
printf("网络设备名称: %s\n", dev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("获取网络设备名称失败: %s\n", err_buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取网卡的网络号和子网掩码
|
||||||
|
bpf_u_int32 netip;
|
||||||
|
bpf_u_int32 netmask;
|
||||||
|
if ((pcap_lookupnet(dev, &netip, &netmask, NULL)) == 0)
|
||||||
|
{
|
||||||
|
unsigned char ip[16] = "";
|
||||||
|
unsigned char mask[16] = "";
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &netip, ip, 16); // inet_ntop()将网络地址转换成“.”点隔的字符串格式
|
||||||
|
inet_ntop(AF_INET, &netmask, mask, 16);
|
||||||
|
|
||||||
|
printf("网卡网络号: %s 子网掩码: %s\n", ip, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
// pcap_next 接收下一条数据
|
||||||
|
#include <pcap.h> // libpcap头文件
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <arpa/inet.h> // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 1. 获取可用的网络设备名称
|
||||||
|
char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备
|
||||||
|
if (dev != NULL)
|
||||||
|
{
|
||||||
|
printf("网络设备名称: %s\n", dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 打开网络设备, 开始捕获数据
|
||||||
|
char err_buf[PCAP_ERRBUF_SIZE] = "";
|
||||||
|
pcap_t *cap = pcap_open_live(dev, 128, 0, 0, err_buf);
|
||||||
|
if (cap == NULL)
|
||||||
|
{
|
||||||
|
printf("open pcap fail: %s\n", err_buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 开始捕获数据
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
struct pcap_pkthdr cap_hdr;
|
||||||
|
bzero(&cap_hdr, sizeof(cap_hdr));
|
||||||
|
const u_char *data = pcap_next(cap, &cap_hdr);
|
||||||
|
if (cap_hdr.len > 0)
|
||||||
|
{
|
||||||
|
printf("数据包长度: %d, 实际长度: %d\n", cap_hdr.caplen, cap_hdr.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分析 mac 报文的数据
|
||||||
|
struct ether_header *mac_hdr = (struct ether_header *)data;
|
||||||
|
unsigned char src_mac[18] = "";
|
||||||
|
unsigned char dst_mac[18] = "";
|
||||||
|
|
||||||
|
sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
mac_hdr->ether_dhost[0],
|
||||||
|
mac_hdr->ether_dhost[1],
|
||||||
|
mac_hdr->ether_dhost[2],
|
||||||
|
mac_hdr->ether_dhost[3],
|
||||||
|
mac_hdr->ether_dhost[4],
|
||||||
|
mac_hdr->ether_dhost[5]);
|
||||||
|
|
||||||
|
sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
mac_hdr->ether_shost[0],
|
||||||
|
mac_hdr->ether_shost[1],
|
||||||
|
mac_hdr->ether_dhost[2],
|
||||||
|
mac_hdr->ether_shost[3],
|
||||||
|
mac_hdr->ether_shost[4],
|
||||||
|
mac_hdr->ether_shost[5]);
|
||||||
|
|
||||||
|
unsigned short mac_type = ntohs(mac_hdr->ether_type);
|
||||||
|
|
||||||
|
printf("type(%#x) src mac: %s, dst mac: %s\n", mac_type, src_mac, dst_mac);
|
||||||
|
if (mac_type == 0x0800)
|
||||||
|
{
|
||||||
|
// 分析 ip 报文的数据
|
||||||
|
struct iphdr *ip_hdr = (struct iphdr *)(data + sizeof(struct ether_header));
|
||||||
|
u_char src_ip[INET_ADDRSTRLEN] = "";
|
||||||
|
u_char dst_ip[INET_ADDRSTRLEN] = "";
|
||||||
|
inet_ntop(AF_INET, &ip_hdr->saddr, src_ip, INET_ADDRSTRLEN);
|
||||||
|
inet_ntop(AF_INET, &ip_hdr->daddr, dst_ip, INET_ADDRSTRLEN);
|
||||||
|
|
||||||
|
printf("ip type(%d) %s->%s\n", ip_hdr->protocol, src_ip, dst_ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭网卡设备
|
||||||
|
pcap_close(cap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
// pcap_loop 循环接收数据
|
||||||
|
#include <pcap.h> // libpcap头文件
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <arpa/inet.h> // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *caphdr, const u_char *data);
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 1. 获取可用的网络设备名称
|
||||||
|
char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备
|
||||||
|
if (dev != NULL)
|
||||||
|
{
|
||||||
|
printf("网络设备名称: %s\n", dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 打开网络设备, 开始捕获数据
|
||||||
|
char err_buf[PCAP_ERRBUF_SIZE] = "";
|
||||||
|
pcap_t *cap = pcap_open_live(dev, 128, 0, 0, err_buf);
|
||||||
|
if (cap == NULL)
|
||||||
|
{
|
||||||
|
printf("open pcap fail: %s\n", err_buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环捕获数据
|
||||||
|
pcap_loop(cap, -1, recv_data_handler, NULL);
|
||||||
|
|
||||||
|
// 关闭网卡设备
|
||||||
|
pcap_close(cap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *cap_hdr, const u_char *data)
|
||||||
|
{
|
||||||
|
if (cap_hdr->caplen > 0)
|
||||||
|
{
|
||||||
|
printf("数据包长度: %d, 实际长度: %d\n", cap_hdr->caplen, cap_hdr->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
// pcap_loop 循环接收数据
|
||||||
|
#include <pcap.h> // libpcap头文件
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <arpa/inet.h> // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *caphdr, const u_char *data);
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 1. 获取可用的网络设备名称
|
||||||
|
char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备
|
||||||
|
if (dev != NULL)
|
||||||
|
{
|
||||||
|
printf("网络设备名称: %s\n", dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 打开网络设备, 开始捕获数据
|
||||||
|
char err_buf[PCAP_ERRBUF_SIZE] = "";
|
||||||
|
pcap_t *cap = pcap_open_live(dev, 128, 0, 0, err_buf);
|
||||||
|
if (cap == NULL)
|
||||||
|
{
|
||||||
|
printf("open pcap fail: %s\n", err_buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编译过滤规则, 成功则设置过滤规则
|
||||||
|
char filter[] = "udp dst port 8001";
|
||||||
|
struct bpf_program program; // 过滤器程序结构体,采用bpf(伯克利包过滤器)
|
||||||
|
if (pcap_compile(cap, &program, filter, 0, 0xffffff00) == 0)
|
||||||
|
{
|
||||||
|
pcap_setfilter(cap, &program);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环捕获数据
|
||||||
|
pcap_loop(cap, -1, recv_data_handler, NULL);
|
||||||
|
|
||||||
|
// 关闭网卡设备
|
||||||
|
pcap_close(cap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *cap_hdr, const u_char *data)
|
||||||
|
{
|
||||||
|
if (cap_hdr->caplen > 0)
|
||||||
|
{
|
||||||
|
printf("数据包长度: %d, 实际长度: %d\n", cap_hdr->caplen, cap_hdr->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
Loading…
Reference in New Issue