133 lines
5.2 KiB
C
133 lines
5.2 KiB
C
|
/*
|
|||
|
* 写一个网络数据分析器
|
|||
|
* 要求:
|
|||
|
* 1、对 arp/ip/tcp/udp 数据进行区分。
|
|||
|
* 2、把数据包中的源信息,目的信息等重要的信息打印出来。
|
|||
|
*/
|
|||
|
#include <stdio.h>
|
|||
|
#include <pcap/pcap.h>
|
|||
|
#include <netinet/in.h>
|
|||
|
#include <arpa/inet.h>
|
|||
|
#include <string.h> // memset
|
|||
|
#include <net/ethernet.h> // ether_header
|
|||
|
#include <netinet/ip.h> // ip
|
|||
|
#include <netinet/if_ether.h> // ether_arp
|
|||
|
#include <unistd.h> // sleep
|
|||
|
|
|||
|
int main(int argc, char const *argv[])
|
|||
|
{
|
|||
|
char errbuf[PCAP_ERRBUF_SIZE]; // 用于存储错误信息的缓冲区
|
|||
|
char *dev = pcap_lookupdev(errbuf); // 获取网络接口
|
|||
|
if (dev == NULL) // 获取网络接口失败
|
|||
|
{
|
|||
|
printf("pcap_lookupdev error: %s\n", errbuf);
|
|||
|
return -1;
|
|||
|
}
|
|||
|
printf("网络接口: %s\n", dev);
|
|||
|
|
|||
|
// 获取网卡的网络号,掩码地址
|
|||
|
bpf_u_int32 netip, netmask;
|
|||
|
if (pcap_lookupnet(dev, &netip, &netmask, NULL) == 0)
|
|||
|
{
|
|||
|
unsigned char ip[INET_ADDRSTRLEN] = "";
|
|||
|
unsigned char mask[INET_ADDRSTRLEN] = "";
|
|||
|
|
|||
|
inet_ntop(AF_INET, &netip, ip, INET_ADDRSTRLEN);
|
|||
|
inet_ntop(AF_INET, &netmask, mask, INET_ADDRSTRLEN);
|
|||
|
printf("网络地址: %s 掩码地址: %s\n", ip, mask);
|
|||
|
}
|
|||
|
|
|||
|
// 打开网络设备,开始捕获数据
|
|||
|
pcap_t *pcap_handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
|
|||
|
if (pcap_handle == NULL)
|
|||
|
{
|
|||
|
printf("pcap_open_live error: %s\n", errbuf);
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
while (1)
|
|||
|
{
|
|||
|
struct pcap_pkthdr pcap_hdr; // 数据包头
|
|||
|
memset(&pcap_hdr, 0, sizeof(pcap_hdr)); // 清空结构体
|
|||
|
const u_char *packet = pcap_next(pcap_handle, &pcap_hdr); // 获取数据包
|
|||
|
if (packet == NULL)
|
|||
|
{
|
|||
|
printf("pcap_next error\n");
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
// 分析 ethernet 报文类型
|
|||
|
// 如果是 arp 报文,则打印 arp 报文信息
|
|||
|
// 如果是 ip 报文,则打印 ip 报文信息
|
|||
|
struct ether_header *eth_hdr = (struct ether_header *)packet;
|
|||
|
// 拆分源 mac 地址和目的 mac 地址
|
|||
|
unsigned char src_mac_x[ETHER_ADDR_LEN] = ""; // 源 mac 地址
|
|||
|
unsigned char dst_mac_x[ETHER_ADDR_LEN] = ""; // 目的 mac 地址
|
|||
|
memcpy(src_mac_x, eth_hdr->ether_shost, ETHER_ADDR_LEN); // 拷贝源 mac 地址
|
|||
|
memcpy(dst_mac_x, eth_hdr->ether_dhost, ETHER_ADDR_LEN); // 拷贝目的 mac 地址
|
|||
|
|
|||
|
char src_mac[18] = ""; // 存储 MAC 地址的字符串
|
|||
|
char dst_mac[18] = ""; // 存储 MAC 地址的字符串
|
|||
|
|
|||
|
// 将 MAC 地址转换成字符串
|
|||
|
sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
|||
|
src_mac_x[0], src_mac_x[1], src_mac_x[2], src_mac_x[3], src_mac_x[4], src_mac_x[5]);
|
|||
|
|
|||
|
sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
|||
|
dst_mac_x[0], dst_mac_x[1], dst_mac_x[2], dst_mac_x[3], dst_mac_x[4], dst_mac_x[5]);
|
|||
|
|
|||
|
if (ntohs(eth_hdr->ether_type) == ETHERTYPE_ARP)
|
|||
|
{
|
|||
|
// 拆分源 ip 地址和目的 ip 地址
|
|||
|
unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源 ip 地址
|
|||
|
unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的 ip 地址
|
|||
|
struct ether_arp *arp_hdr = (struct ether_arp *)(packet + sizeof(struct ether_header));
|
|||
|
inet_ntop(AF_INET, arp_hdr->arp_spa, src_ip, INET_ADDRSTRLEN); // 拷贝源 ip 地址
|
|||
|
inet_ntop(AF_INET, arp_hdr->arp_tpa, dst_ip, INET_ADDRSTRLEN); // 拷贝目的 ip 地址
|
|||
|
|
|||
|
printf("arp 报文\n");
|
|||
|
printf("源地址: %s\t\t目的地址: %s\n源MAC: %s\t目的MAC: %s\n", src_ip, dst_ip, src_mac, dst_mac); // 打印 arp 报文信息
|
|||
|
}
|
|||
|
else if (ntohs(eth_hdr->ether_type) == ETHERTYPE_IP)
|
|||
|
{
|
|||
|
// 拆分源 ip 地址和目的 ip 地址
|
|||
|
unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源 ip 地址
|
|||
|
unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的 ip 地址
|
|||
|
struct ip *ip_hdr = (struct ip *)(packet + sizeof(struct ether_header));
|
|||
|
inet_ntop(AF_INET, &ip_hdr->ip_src, src_ip, INET_ADDRSTRLEN); // 拷贝源 ip 地址
|
|||
|
inet_ntop(AF_INET, &ip_hdr->ip_dst, dst_ip, INET_ADDRSTRLEN); // 拷贝目的 ip 地址
|
|||
|
|
|||
|
printf("ip 报文\n");
|
|||
|
|
|||
|
// 分析 ip 报文类型
|
|||
|
// 如果是 tcp 报文,则打印 tcp 报文信息
|
|||
|
// 如果是 udp 报文,则打印 udp 报文信息
|
|||
|
if (ip_hdr->ip_p == IPPROTO_TCP)
|
|||
|
{
|
|||
|
printf("tcp 报文\n");
|
|||
|
printf("源地址: %s\t\t目的地址: %s\n源MAC: %s\t目的MAC: %s\n", src_ip, dst_ip, src_mac, dst_mac); // 打印 ip 报文信息
|
|||
|
}
|
|||
|
else if (ip_hdr->ip_p == IPPROTO_UDP)
|
|||
|
{
|
|||
|
printf("udp 报文\n");
|
|||
|
printf("源地址: %s\t\t目的地址: %s\n源MAC: %s\t目的MAC: %s\n", src_ip, dst_ip, src_mac, dst_mac); // 打印 ip 报文信息
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
printf("其他报文\n");
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
printf("其他报文\n");
|
|||
|
}
|
|||
|
|
|||
|
sleep(1);
|
|||
|
}
|
|||
|
|
|||
|
// 关闭网络设备
|
|||
|
pcap_close(pcap_handle);
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|