12.3 数据包文件存储的幕后
数据包文件存储的主要函数调用关系如图12-8所示。
图 12-8 数据包文件存储的主要函数调用关系
12.3.1 pcap_dump_open函数
pcap_dump_open函数用于打开一个文件并写入数据包,其原型如下:
pcap_dumper_tpcap_dump_open(pcap_tp,const char*fname)
上述函数中,参数fname为需要打开的用来存储数据包的savefile文件名,-等同于stdout文件;参数p是调用pcap_open_offline或pcap_open_live函数返回的一个pcap结构体。
如果函数pcap_dump_open执行失败则返回NULL。
该函数的具体代码实现如下:
pcap_dumper_tpcap_dump_open(pcap_tp,const char*fname)
{
FILE*f;
int linktype;
/检测数据链路层的类型/
linktype=dlt_to_linktype(p->linktype);
if(linktype==-1){
//数据链路层类型不支持文件转储
return(NULL);
}
linktype|=p->linktype_ext;
/打开转储文件/
if(fname[0]=='-'&&fname[1]=='\0'){
f=stdout;
fname="standard output";
}else{
f=fopen(fname,"wb");
if(f==NULL){
//打开转储文件失败
return(NULL);
}
}
/存储转储文件的头信息/
return(pcap_setup_dump(p,linktype,f,fname));
}
上述代码中,pcap_setup_dump函数主要通过调用sf_write_header函数来设置转储文件的头信息,具体实现代码如下:
static pcap_dumper_tpcap_setup_dump(pcap_tp,int linktype,
FILEf,const charfname)
{
if defned(WIN32)||defned(MSDOS)
if(f==stdout)
SET_BINMODE(f);
else
setbuf(f,NULL);//把文件设置为非缓冲的
endif
/写文件头信息/
if(sf_write_header(f,linktype,p->tzoff,p->snapshot)==-1)
{//写文件失败
……
return(NULL);
}
return((pcap_dumper_t*)f);
}
上述代码中,sf_write_header函数主要是调用fwrite把文件头信息写入转储文件中的。该函数的具体实现代码如下:
static int sf_write_header(FILE*fp,int linktype,int thiszone,int snaplen)
{
struct pcap_fle_header hdr;
hdr.magic=TCPDUMP_MAGIC;
hdr.version_major=PCAP_VERSION_MAJOR;
hdr.version_minor=PCAP_VERSION_MINOR;
hdr.thiszone=thiszone;
hdr.snaplen=snaplen;
hdr.sigfgs=0;
hdr.linktype=linktype;
if(fwrite((char*)&hdr,sizeof(hdr),1,fp)!=1)
return(-1);
return(0);
}