最近公司项目拟定使用tcpflow来分析http协议
分析源代码后才能更好的利用源代码进行二次开发
代码下载地址:https://github.com/simsong/tcpflow
1.从main函数开始分析
第一步:process_infile函数处理-r 和 -R参数的pcap文件解析
//打开pcap离线文件,根据pcap文件格式进行解析
pd = pcap_open_offline(file_path.c_str(), error);
//查找处理某一网络层的函数
handler = find_handler(dlt, infile.c_str());
如果infile值等于空则执行linux下pcap抓包分析的流程
pcap_lookupdev
pcap_open_live
find_handler
pcap_compile
pcap_setfilter
其中pcap_compile和pcap_setfilter是设置过滤器并安装到libpcap中
不管是在线抓包还是分析离线文件pcap格式文件,最终都会调用pcap_loop函数
解析struct pcap_pkthdr hdr; pcap数据包包头结构
/* Read the packet */
if(fread(p->pktbuf,hdr.caplen,1,p->fp)!=1) break; // no more to read
解析pcap文件的实际数据包
/* Process the packet */
(*callback)(user,&hdr,p->pktbuf);
使用callback指向的回调函数来处理数据包包头和真实数据部分
暂时先分析到这里,后续会图文并茂的完整分析下C++版的tcpflow
scanner_info *info;
结构体是在什么地方使用的。
scanner_info结构体中存储有一个packet_callback_t回调函数指针
packet_callback_t *packet_cb; // v2: (output) callback for processing network packets, or NULL
void *packet_user;
定位到load_scanner_packet_handlers,将回调函数的user和packet_cb回调函数指针加入到packet_handlers中
void be13::plugin::load_scanner_packet_handlers()
{
for(scanner_vector::const_iterator it = current_scanners.begin(); it!=current_scanners.end(); it++){
if((*it)->enabled){
const scanner_def *sd = (*it);
if(sd->info.packet_cb){
packet_handlers.push_back(packet_plugin_info(sd->info.packet_user,sd->info.packet_cb));
}
}
}
}
packet_handlers的类型其实就是一个vector数组
typedef std::vector<packet_plugin_info> packet_plugin_info_vector_t;
packet_plugin_info_vector_t packet_handlers; // pcap callback handlers
继续跟踪谁在使用packet_handlers变量
在Plugin.cpp源文件的process_packet函数中
void be13::plugin::process_packet(const be13::packet_info &pi)
{
for(packet_plugin_info_vector_t::iterator it = packet_handlers.begin(); it != packet_handlers.end(); it++){
(*(*it).callback)((*it).user,pi);
}
}
玩linux的时候经常会看到stdin stdout stderr 这3个可以称为终端(Terminal)的标准输入(standard input),标准输出( standard out)和标准错误输出(standard error)。
fprintf(stdout,“process_infile(): deal pcap offline file\r\n”);
离线文件处理流程
{ dl_ethernet, DLT_EN10MB },
{ dl_ethernet, DLT_IEEE802 },
进入dl_ethernet函数,进入be13::plugin::process_packet(pi);函数
在process_packet()函数中
for(packet_plugin_info_vector_t::iterator it = packet_handlers.begin(); it !=packet_handlers.end(); it++)
{
(*(*it).callback)((*it).user,pi);
}
加载并扫描packet_handlers
void be13::plugin::load_scanner_packet_handlers()
{
for(scanner_vector::const_iterator it = current_scanners.begin(); it!=current_scanners.end(); it++){
if((*it)->enabled){
const scanner_def *sd = (*it);
if(sd->info.packet_cb){
packet_handlers.push_back(packet_plugin_info(sd->info.packet_user,sd->info.packet_cb));
}
}
}
}
scan_tcpdemux 设置info结构体的packet_user和packet_cb
packet_cb = packet_handler
packet_handler调用process_pkt
处理ip数据包tcp数据包