报头解析,是通过网络抓包对网络上传输的数据包进行抓取,通过对数据包的每层协议进行分析得到其报文首部信息。抓包对于软件的Debug具有很大的帮助。抓包更多的用于网络安全,比如查找感染病毒的计算机,获取网页的源代码,以及了解攻击者所用方法,追查攻击者的ip地址等。
抓包可以实时捕获并详细显示各种类型数据包,可以通过多种方式过滤数据包,还可以进行多种统计分析。在程序运行的数据交互中,传输的数据一般都是以数据包的形式传输。一般抓包测试多用于通信行业和网络行业的测试。
本文为Linux环境下编写。
#@file makefile
#@biref libpcap project makefile
#@euthor
#@history
# 2022-06-04 created
CPATH=./pcappro/src
OPATH=./pcappro/obj
HPATH=./pcappro/include
# VPATH=./home/wz/libpcap/swpcappro/src ./home/wz/libpcap/pcappro/obj
app:$(OPATH)/main.o $(OPATH)/analyprotocol.o $(OPATH)/pcap.o $(OPATH)/fileio.o
gcc -o $@ $^ -L/usr/./lib/x86_64-linux-gnu/ -lpcap
$(OPATH)/main.o:$(CPATH)/main.c $(HPATH)/pcapproject.h
gcc -c $(CPATH)/main.c -o $(OPATH)/main.o
$(OPATH)/pcap.o:$(CPATH)/pcap.c $(HPATH)/pcapproject.h
gcc -c $(CPATH)/pcap.c -o $(OPATH)/pcap.o
$(OPATH)/analyprotocol.o:$(CPATH)/analyprotocol.c $(HPATH)/pcapproject.h
gcc -c $(CPATH)/analyprotocol.c -o $(OPATH)/analyprotocol.o
$(OPATH)/swfileio.o:$(CPATH)/fileio.c $(HPATH)/pcapproject.h
gcc -c $(CPATH)/fileio.c -o $(OPATH)/fileio.o
.PHONY:clean
clean:
-rm $(OPATH)/*.o
-rm ./*.txt
/*
* @file pcapproject.h
* @brief libpcap项目头文件
* IP、TCP、UDP、以太网结构体的定义
* 分析头部函数的定义
* IO调用的接口
* @author
* @history
* 2022-06-04 created
*/
#ifndef __PCAPPROJECT_H__
#define __PCAPPROJECT_H__
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include <sys/stat.h>
#include<fcntl.h>
#include<pcap.h>
#define BUFSIZE 1518
#define IP_PATH "/home/wz/testlib/libpcap/ip_headers.txt"
#define TCP_PATH "/home/wz/testlib/libpcap/tcp_headers.txt"
#define UDP_PATH "/home/wz/testlib/libpcap/udp_headers.txt"
#define HTTP_PATH "/home/wz/testlib/libpcap/http_headers.txt"
extern int g_tcp_num;
extern int g_udp_num;
extern int g_http_num;
struct ether_header_t
{
unsigned char ether_dhost[6]; /*目的mac*/
unsigned char ether_shost[6]; /*源mac*/
unsigned short ether_type; /*以太网类型*/
};
struct ip_header_t
{
unsigned char header_len:4,
version:4; /*版本信息(前4位),头长度(后4位)*/
unsigned char type_service; /*服务类型*/
unsigned short packet_len; /*数据包长度*/
unsigned short packet_id; /*数据包标识*/
unsigned short slice_info; /*分片使用*/
unsigned char ttl; /*存活时间*/
unsigned char type_protocol; /*协议类型*/
unsigned short check_sum; /*校验和*/
unsigned int sour_ip; /*源ip*/
unsigned int dest_ip; /*目的ip*/
};
struct tcp_header_t
{
unsigned short sour_port; /*源端口号*/
unsigned short dest_port; /*目的端口号*/
unsigned int seq_number; /*序列号*/
unsigned int ack_number; /*确认号*/
unsigned char reserved_1:4; /*保留6位中的4位首部长度*/
unsigned char header_len:4; /*tcp头部长度*/
unsigned char fin:1, /*6位标志*/
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
reseverd_2:2; /*保留6位中的2位*/
unsigned short window_size; /*窗口大小*/
unsigned short check_sum; /*校验和*/
unsigned short surgent_pointer; /*紧急数据偏移量*/
};
struct udp_header_t
{
unsigned short sour_port; /*源端口号*/
unsigned short dest_port; /*目的端口号*/
unsigned short length; /*数据包长度*/
unsigned short check_sum; /*校验和*/
};
void sw_ethernet_protocol_callback(unsigned char * argument,\
const struct pcap_pkthdr * packet_header,\
const unsigned char * packet_content);
int analy_ip_and_io(const unsigned char * packet_content);
int analy_tcp_and_io(const unsigned char * packet_content,const unsigned int ipheader_len);
int analy_udp_and_io(const unsigned char * packet_content,const unsigned int ipheader_len);
int analy_http_and_io(const unsigned char * packet_content,const unsigned int iptcpheader_len);
int ip_file_io(const struct ip_header_t * ip_header);
int tcp_file_io(const struct tcp_header_t * tcp_header);
int udp_file_io(const struct udp_header_t * udp_header);
int http_file_io(const char * protocol_header);
#endif /*__PCAPPROJECT_H__*/
#include"../include/pcapproject.h"
int g_tcp_num = 1;
int g_udp_num = 1;
int g_http_num = 1;
int main()
{
char error_content[PCAP_ERRBUF_SIZE] = {'0'}; /*出错信息*/
pcap_t * pcap_handle = NULL;
unsigned int net_ip = 0; /*网络地址*/
unsigned int net_mask = 0; /*子网掩码*/
pcap_if_t * net_interface = NULL; /*网卡信息*/
int func_ret = 0;
struct bpf_program bpf_filter;
char bpf_filter_string[] = "ip"; /*只捕获ip包*/
/*char bpf_filter_string[] = "dst port 80"; 只捕获80端口的数据包*/
/*获取网络设备名称*/
func_ret = pcap_findalldevs( &net_interface, error_content );
if( -1 == func_ret )
{
perror( "pcap_findalldevs" );
return -1;
}
/*取第一个网络设备名称*/
char * net_interface_name = net_interface->name;
printf( "net_interface_name = %s\n",net_interface_name );
/*获取网络设备的ip及mac地址*/
func_ret = pcap_lookupnet( net_interface_name, &net_ip,\
&net_mask, error_content );
if( -1 == func_ret )
{
perror( "pcap_lookupnet" );
return -1;
}
/*打开网络接口*/
pcap_handle = pcap_open_live( net_interface_name, BUFSIZE, 1, \
0, error_content );
if( NULL == pcap_handle )
{
perror("pcap_open_live");
return -1;
}
/*编译BPF过滤规则*/
func_ret = pcap_compile( pcap_handle, &bpf_filter, bpf_filter_string,\
0, net_mask );
if( -1 == func_ret )
{
perror("pcap_compile");
return -1;
}
/*设置过滤器规则*/
func_ret = pcap_setfilter( pcap_handle, &bpf_filter );
if( -1 == func_ret )
{
perror("pcap_setfilter");
return -1;
}
/*循环获取数据包*/
while(1)
{
if( pcap_loop(pcap_handle, 1, \
ethernet_protocol_callback, NULL ) < 0 )
{
perror( "pcap_loop" );
}
if( 63 <= (g_tcp_num + g_udp_num + g_http_num) )
{
printf("Data collection completed\n");
break;
}
}
pcap_close( pcap_handle );
return 0;
}
#include"../include/pcapproject.h"
int analy_ip_and_io(const unsigned char * packet_content)
{
printf( "----------------------------------------------\n" );
if( NULL == packet_content)
{
printf("IP_func input error\n");
return -1;
}
struct ip_header_t * ip_protocol = NULL;
int func_ret = 0;
unsigned char * ip_sour = NULL;
unsigned char * ip_dest = NULL;
ip_protocol = (struct ip_header_t *)(packet_content + 14);
ip_sour = (unsigned char *)&ip_protocol->sour_ip;
ip_dest = (unsigned char *)&ip_protocol->dest_ip;
printf("The network layer is IP protocol\n");
printf("IP version = IPv%d\n",ip_protocol->version);
printf("IP header len = %d\n",(ip_protocol->header_len) * 4 );
printf("IP type service : %d\n",ip_protocol->type_service);
printf("IP packet len : %d\n",ntohs(ip_protocol->packet_len));
printf("IP packet id : %d\n",ntohs(ip_protocol->packet_id));
printf("IP slice info : %d\n",ntohs(ip_protocol->slice_info));
printf("IP time to live : %d\n",ip_protocol->ttl);
printf("IP transport type: 0x%04x\n",ip_protocol->type_protocol);
printf("IP check sum : %d\n",ntohs(ip_protocol->check_sum));
printf("IP sour : %d.%d.%d.%d\n",*(ip_sour),*(ip_sour + 1),*(ip_sour + 2),*(ip_sour + 3));
printf("IP dest : %d.%d.%d.%d\n",*(ip_dest),*(ip_dest + 1),*(ip_dest + 2),*(ip_dest + 3));
func_ret = ip_file_io(ip_protocol);
if( -1 == func_ret )
{
printf("ip file_io error\n");
}
itch(ip_protocol->type_protocol)
{
case 0x0006:
func_ret = analy_tcp_and_io(packet_content,(ip_protocol->header_len) * 4 );
if( -1 == func_ret)
{
printf("analy_tcp error\n");
return 0;
}
break;
case 0x0011:
func_ret = analy_udp_and_io( packet_content,(ip_protocol->header_len) * 4 );
if( -1 == func_ret)
{
printf("analy_udp error\n");
return 0;
}
break;
default:
printf("other\n");
break;
}
return 0;
}
int analy_tcp_and_io(const unsigned char * packet_content,const unsigned int ipheader_len)
{
printf( "----------------------------------------------\n" );
if( NULL == packet_content || ipheader_len == 0 )
{
printf("TCP_func input error\n");
return -1;
}
int func_ret = 0;
struct tcp_header_t * tcp_protocol = NULL;
tcp_protocol = (struct tcp_header_t *)(packet_content + 14 + ipheader_len);
printf("The transport layer is TCP protocol\n");
printf("TCP dest port = %d\n", ntohs(tcp_protocol->dest_port));
printf("TCP sour port = %d\n", ntohs(tcp_protocol->sour_port));
printf("TCP Seq number = %u\n", (unsigned int)ntohl(tcp_protocol->seq_number));
printf("TCP Ack number = %u\n", (unsigned int)ntohl(tcp_protocol->ack_number));
printf("TCP_header_len = %d\n",(tcp_protocol->header_len) * 4);
printf("FIN : %d; SYN : %d; RST : %d; ",tcp_protocol->fin,tcp_protocol->syn,tcp_protocol->rst);
printf("PSH : %d; ACK : %d; URG : %d; \n",tcp_protocol->psh,tcp_protocol->ack,tcp_protocol->urg);
printf("TCP Window size = %d\n", ntohs(tcp_protocol->window_size));
printf("TCP check sum = %d\n", ntohs(tcp_protocol->check_sum));
printf("TCP surgent_pointer = %d\n", ntohs(tcp_protocol->surgent_pointer));
func_ret = tcp_file_io(tcp_protocol);
if( -1 == func_ret)
{
printf("TCP file_io error\n");
}
if( 80 == ntohs(tcp_protocol->dest_port) || 80 == ntohs(tcp_protocol->sour_port) )
{
func_ret = analy_http_and_io(packet_content,((tcp_protocol->header_len) * 4) + ipheader_len );
if( -1 == func_ret )
{
printf("analy_http error\n");
}
}
return 0;
}
int analy_udp_and_io(const unsigned char * packet_content,const unsigned int ipheader_len)
{
printf( "----------------------------------------------\n" );
if( NULL == packet_content || ipheader_len == 0 )
{
printf("UDP_func input error\n");
return -1;
}
int func_ret = 0;
int udp_io_fd = 0;
struct udp_header_t * udp_protocol = NULL;
printf("The transport layer is UDP protocol\n");
udp_protocol = (struct udp_header_t *)\
(packet_content + 14 + ipheader_len);
printf("UDP dest port = %d\n", ntohs(udp_protocol->dest_port));
printf("UDP sour port = %d\n", ntohs(udp_protocol->sour_port));
printf("UDP check num = %d\n", ntohs(udp_protocol->check_sum));
printf("UDP packet length = %d\n", ntohs(udp_protocol->length));
func_ret = udp_file_io(udp_protocol);
if( -1 == func_ret)
{
printf("UDP file_io error\n");
}
printf("func_ret = %d\n",func_ret);
return 0;
}
int analy_http_and_io(const unsigned char * packet_content,const unsigned int iptcpheader_len)
{
printf( "----------------------------------------------\n" );
if( NULL == packet_content || iptcpheader_len == 0 )
{
printf("HTTP_func input error\n");
return -1;
}
int func_ret = 0;
char * http_header_p = NULL;
char * http_header_end_p = NULL;
http_header_p = (char *)packet_content +14 + iptcpheader_len;
if( NULL == strstr( http_header_p, "HTTP/") )
{
printf("THe application layer is not HTTP protocol\n");
return 0;
}
printf( "THe application layer is HTTP protocol\n" );
func_ret = http_file_io(http_header_p);
if( -1 == func_ret)
{
printf("TCP file_io error\n");
}
return 0;
}
#include"../include/pcapproject.h"
/*回调函数*/
void ethernet_protocol_callback( unsigned char * argument,\
const struct pcap_pkthdr * packet_header,\
const unsigned char * packet_content )
{
if( NULL == packet_header || NULL == packet_content )
{
printf("Ethernet_func input error\n");
return;
}
unsigned char * mac_string;
struct ether_header_t * ethernet_protocol;
unsigned short ethernet_type; /*以太网类型*/
int func_ret = 0;
printf( "----------------------------------------------\n" );
/*转换时间*/
printf( "%s\n",ctime( ( time_t * )&( packet_header->ts.tv_sec ) ) );
printf("The layer is ethernet protocol\n");
/*强制转换数据类型*/
ethernet_protocol = ( struct ether_header_t * ) packet_content;
/*获取源mac地址*/
mac_string = ( unsigned char *) ethernet_protocol->ether_shost;
printf( "Mac Source Address is %02x:%02x:%02x:%02x:%02x:%02x\n",\
*(mac_string + 0), *(mac_string + 1), \
*(mac_string + 2), *(mac_string + 3), \
*(mac_string + 4), *(mac_string + 5) );
/*获取目的mac*/
mac_string = (unsigned char *)ethernet_protocol->ether_dhost;
printf("Mac Destination Address is %02x:%02x:%02x:%02x:%02x:%02x\n",\
*(mac_string + 0), *(mac_string + 1), \
*(mac_string + 2), *(mac_string + 3), \
*(mac_string + 4), *(mac_string + 5) );
/*获取以太网类型*/
ethernet_type = ntohs( ethernet_protocol->ether_type );
printf("Ethernet type is :0x%04x\n", ethernet_type);
itch(ethernet_type)
{
case 0x0800:
func_ret = analy_ip_and_io(packet_content);
if( -1 == func_ret )
{
printf("analy_ip error\n");
return;
}
break;
case 0x0806:
printf("The network layer is ARP protocol\n");
break;
case 0x0835:
printf("The network layer is RARP protocol\n");
break;
default:
break;
}
/*usleep( 800*1000 );*/
return;
}
#include"../include/pcapproject.h"
int _ip_file_io(const struct ip_header_t * ip_header)
{
if( NULL == ip_header )
{
printf("ip io input error\n");
return -1;
}
FILE * io_fd = NULL;
int func_ret = 0;
static int ip_number = 1;
printf("Data packet capture:%d\n",ip_number);
io_fd = fopen( IP_PATH, "a" );
if( NULL == io_fd )
{
perror("ip file open error\n");
return -1;
}
unsigned char * ip_sour = NULL;
unsigned char * ip_dest = NULL;
ip_sour = (unsigned char *)&ip_header->sour_ip;
ip_dest = (unsigned char *)&ip_header->dest_ip;
fprintf(io_fd,"Data packet capture number:%d\n",ip_number);
fprintf(io_fd,"IP version = IPv%d\n",ip_header->version);
fprintf(io_fd,"IP header len = %d\n",(ip_header->header_len) * 4 );
fprintf(io_fd,"IP type service : %d\n",ip_header->type_service);
fprintf(io_fd,"IP packet len : %d\n",ntohs(ip_header->packet_len));
fprintf(io_fd,"IP packet id : %d\n",ntohs(ip_header->packet_id));
fprintf(io_fd,"IP slice info : %d\n",ntohs(ip_header->slice_info));
fprintf(io_fd,"IP time to live : %d\n",ip_header->ttl);
fprintf(io_fd,"IP transport type: 0x%04x\n",ip_header->type_protocol);
fprintf(io_fd,"IP check sum : %d\n",ntohs(ip_header->check_sum));
fprintf(io_fd,"IP sour : %d.%d.%d.%d\n",*(ip_sour),*(ip_sour + 1),\
*(ip_sour + 2),*(ip_sour + 3));
fprintf(io_fd,"IP dest : %d.%d.%d.%d\n",*(ip_dest),*(ip_dest + 1),\
*(ip_dest + 2),*(ip_dest + 3));
fprintf(io_fd,"source data:\n");
for( int i = 1; i <= 20; i++)
{
if( 1 == i )
{
fprintf(io_fd,"0000\t");
}
fprintf(io_fd,"%02x ",*((unsigned char *)ip_header+i-1));
if( 0 == i%8 )
{
fprintf(io_fd," ");
}
if( 0 == i%16 )
{
fprintf(io_fd,"\n");
fprintf(io_fd,"%.4x\t",i/16);
}
}
fprintf(io_fd,"\n\n");
func_ret = fclose( io_fd);
if( -1 == func_ret )
{
perror("file close error\n");
return -1;
}
ip_number++;
return 0;
}
int _tcp_file_io(const struct tcp_header_t * tcp_header)
{
if( NULL == tcp_header )
{
printf("tcp io input error\n");
return -1;
}
if( 20 < g_tcp_num )
{
printf("20 TCP data packets have been collected\n");
return 0;
}
printf("Data packet capture:%d\n",g_tcp_num);
int func_ret = 0;
FILE * io_fd = NULL;
io_fd = fopen( TCP_PATH, "a" );
if( NULL == io_fd )
{
perror("fopen error");
return -1;
}
fprintf(io_fd,"Data packet capture number:%d\n",g_tcp_num);
fprintf(io_fd,"TCP dest port = %d\n", ntohs(tcp_header->dest_port));
fprintf(io_fd,"TCP sour port = %d\n", ntohs(tcp_header->sour_port));
fprintf(io_fd,"TCP Seq number = %u\n", ntohl(tcp_header->seq_number));
fprintf(io_fd,"TCP Ack number = %u\n", ntohl(tcp_header->ack_number));
fprintf(io_fd,"TCP_header_len = %d\n",(tcp_header->header_len) * 4);
fprintf(io_fd,"flag:FIN : %d;\n\tSYN : %d;\n ",tcp_header->fin,tcp_header->syn);
fprintf(io_fd,"\tRST : %d;\n\tPSH : %d;\n",tcp_header->rst,tcp_header->psh);
fprintf(io_fd,"\tACK : %d;\n\tURG : %d;\n",tcp_header->ack,tcp_header->urg);
fprintf(io_fd,"TCP Window size = %d\n", ntohs(tcp_header->window_size));
fprintf(io_fd,"TCP check sum = %d\n", ntohs(tcp_header->check_sum));
fprintf(io_fd,"TCP surgent_pointer = %d\n", ntohs(tcp_header->surgent_pointer));
fprintf(io_fd,"source data:\n");
for( int i = 1; i <= 20; i++ )
{
if( 1 == i )
{
fprintf(io_fd,"0000\t");
}
fprintf(io_fd,"%02x ",*((unsigned char *)tcp_header+i-1));
if( 0 == i%8 )
{
fprintf(io_fd," ");
}
if( 0 == i%16 )
{
fprintf(io_fd,"\n");
fprintf(io_fd,"%.4x\t",i/16);
}
}
fprintf(io_fd,"\n\n");
func_ret = fclose( io_fd);
if( -1 == func_ret )
{
perror("tcp file close error\n");
return -1;
}
g_tcp_num++;
return 0;
}
int _udp_file_io(const struct udp_header_t * udp_header)
{
if( NULL == udp_header )
{
printf("udp io input error\n");
return -1;
}
if( 20 < g_udp_num )
{
printf("20 UDP data packets have been collected\n");
return 0;
}
printf("Data packet capture:%d\n",g_udp_num);
FILE * io_fd = NULL;
int func_ret = 0;
io_fd = fopen( UDP_PATH, "a" );
if( NULL == io_fd )
{
perror("udp file open error\n");
return -1;
}
fprintf(io_fd,"Data packet capture number:%d\n",g_udp_num);
fprintf(io_fd,"UDP sour port = %d\n", ntohs(udp_header->sour_port));
fprintf(io_fd,"UDP dest port = %d\n", ntohs(udp_header->dest_port));
fprintf(io_fd,"UDP check num = %d\n", ntohs(udp_header->check_sum));
fprintf(io_fd,"UDP packet length = %d\n", ntohs(udp_header->length));
fprintf(io_fd,"source data:\n");
for( int i = 1; i <= 8; i++ )
{
if( 1 == i )
{
fprintf(io_fd,"0000\t");
}
fprintf(io_fd,"%02x ",*((unsigned char *)udp_header+i-1));
}
fprintf(io_fd,"\n\n");
func_ret = fclose( io_fd);
if( -1 == func_ret )
{
perror("udp file close error\n");
return -1;
}
g_udp_num++;
return 0;
}
int _http_file_io(const char * http_header)
{
if( NULL == http_header )
{
printf("http io input error\n");
return -1;
}
FILE * io_fd = NULL;
int func_ret = 0;
int header_len = 0;
char * http_header_end_p = NULL;
if( 20 < g_http_num )
{
printf("20 HTTP data packets have been collected\n");
return 20;
}
printf("Data packet capture:%d\n",g_http_num);
http_header_end_p = strstr( http_header, "\r\n\r\n" );
if( NULL == http_header_end_p )
{
perror("strstr error\n");
return -1;
}
header_len = strlen(http_header) - strlen(http_header_end_p);
io_fd = fopen( HTTP_PATH, "a" );
if( NULL == io_fd )
{
perror("http file open error\n");
return -1;
}
fprintf(io_fd,"Data packet capture number:%d\n",g_http_num);
func_ret = fwrite( http_header, header_len, 1, io_fd);
if( 0 == func_ret )
{
perror("fwrite error\n");
return -1;
}
fprintf(io_fd,"\nsource data:\n");
for(int i = 1 ; i < header_len + 1; i++)
{
if( 1 == i )
{
fprintf(io_fd,"0000\t");
}
fprintf(io_fd,"%02x ",*((unsigned char *)http_header+i-1));
if( 0 == i%8 )
{
fprintf(io_fd," ");
}
if( 0 == i%16 )
{
fprintf(io_fd,"\n");
fprintf(io_fd,"%.4x\t",i/16);
}
}
fprintf(io_fd,"\n\n");
func_ret = fclose( io_fd);
if( -1 == func_ret )
{
perror("http file close error\n");
return -1;
}
fprintf(stdout,"%s\n",http_header);
g_http_num++;
return 0;
}