头文件pcap_format.h代码:
/* 分析解析pcap文件协议格式。
* pcap格式文件可由tcpdump或者wireshark生成,文件格式组成如下:
* file header
* packet header
* packet data
* packet header
* packet data
* ......
* 其中,file header为24字节,packet header为16字节,packet data为
* 变长数据,其长度由packet header中数据帧长度字段(caplen)决定。
*
* 本代码主要为了解决数字测试仪回放数字录波器的录波文件(pcap格式文
* 件)而编写的。
*
* 本代码支持win32平台和linux平台。
*
* Copyright,lizhi<ibox>
*
* 2012-10-10 V1.0 lizhi<QQ:252240557,msn:ddgooo@hotmail.com> created
*
*/
#ifndef __INCLUDE_PCAP_FORMAT_H
#define __INCLUDE_PCAP_FORMAT_H
/*
* 头文件
*/
#include "base_type.h"
#if defined (__cplusplus)
extern "C" {
#endif /* defined (__cplusplus) */
/*
* 宏开关 定义为文件读写
*/
#define PCAP_IOFILE
/*
* 宏定义文件的读写操作,可以根据需要改写该接口,如重定义
* 为网口的recv\send、串口r\w等。
*
* _my_read_pcap_bufn/_my_read_pcap_bufn/_my_check_pcap_ptr - pcap的读写操作以及句柄检查接口
* @pfd: 读写地址,可以为文件的fd、或者buffer地址等
* @buf: 缓冲区地址
* @count: 需要读写的字节数
*
*/
#if defined(PCAP_IOFILE)
typedef int _my_pcap_ioptr;
#define _my_read_pcap_bufn(pfd, buf, count) \
do { \
if (read((pfd), (buf), (count)) <= 0) { \
(pfd) = -1; \
} \
} while(0);
#define _my_write_pcap_bufn(pfd, buf, count) \
do { \
if (write((pfd), (buf), (count)) <= 0) { \
(pfd) = -1; \
} \
} while(0);
#define _my_check_pcap_ptr(pfd) \
(((pfd) != -1) && ((pfd) != 0))
#elif defined(PCAP_IOBUFFER)
typedef u8* _my_pcap_ioptr;
#define _my_read_pcap_bufn(pfd, buf, count) \
do { \
memcpy((buf), (pfd), (count)); \
(pfd) += (count); \
} while(0);
#define _my_write_pcap_bufn(pfd, buf, count) \
do { \
memcpy((pfd), (buf), (count)); \
(pfd) += (count); \
} while(0);
#define _my_check_pcap_ptr(pfd) \
(((pfd) != -1) && ((pfd) != 0))
#endif
/*
* 定义pcap文件格式中的头部信息(文件头部、数据包头部)的长度。
*
*/
#define PCAP_FILE_HEAD_SIZE 24
#define PCAP_PACKET_HEAD_SIZE 16
/*
* pcap文件版本号(主版本号、次版本号)定义。
*
*/
#define PCAP_FILE_VERSION_MAJOR 2
#define PCAP_FILE_VERSION_MINOR 4
/*
* pcap文件常用链路类型定义,最常用类型为1;基本描述:
* 0:BSD loopback devices, except for later OpenBSD
* 1:Ethernet, and Linux loopback devices
* 6:802.5 Token Ring
* 7:ARCnet
* 8:SLIP
* 9:PPP
* 10:FDDI
* 100:LLC/SNAP-encapsulated ATM
* 101:“raw IP”, with no link
* 102:BSD/OS SLIP
* 103:BSD/OS PPP
* 104:Cisco HDLC
* 105:802.11
* 108:later OpenBSD loopback devices (with the AF_value in network byte order)
* 113:special Linux “cooked” capture
* 114:LocalTalk
*
*/
#define PCAP_FILE_LINK_TYPE_BSD 0
#define PCAP_FILE_LINK_TYPE_ETHERNET 1
#define PCAP_FILE_LINK_TYPE_802D5 6
#define PCAP_FILE_LINK_TYPE_ARCNET 7
#define PCAP_FILE_LINK_TYPE_SLIP 8
#define PCAP_FILE_LINK_TYPE_PPP 9
#define PCAP_FILE_LINK_TYPE_FDDI 10
#define PCAP_FILE_LINK_TYPE_LLC_SNAPATM 100
#define PCAP_FILE_LINK_TYPE_RAW_IP 101
#define PCAP_FILE_LINK_TYPE_BSD_OSSLIP 102
#define PCAP_FILE_LINK_TYPE_BSD_OSPPP 103
#define PCAP_FILE_LINK_TYPE_CISCOHDLC 104
#define PCAP_FILE_LINK_TYPE_802D11 105
#define PCAP_FILE_LINK_TYPE_OPENBSD 108
#define PCAP_FILE_LINK_TYPE_LINUXCOOKED 113
#define PCAP_FILE_LINK_TYPE_LOCALTALK 114
/*
* pcap_file_head - pcap(文件)头结构体,由24字节组成.
* @magic: 4字节, 用来识别文件自己和字节顺序。0xa1b2c3d4用来表示按照原来的顺序读取,
* 0xd4c3b2a1表示下面的字节都要交换顺序读取。一般,我们使用0xa1b2c3d4;
* 保持网络字节顺序;
* @major: 2字节, 主版本号;
* @minor: 2字节, 次版本号;
* @thiszone:4字节, 时区。GMT和本地时间的相差,用秒来表示。如果本地的时区是GMT,那么这
* 个值就设置为0.这个值一般也设置为0
* @sigfigs: 4字节, 精确时间戳,并未使用,目前全为0;
* @snaplen: 4字节, 抓包最大长度,如果要抓全,设为0x0000ffff(65535),tcpdump -s 0就
* 是设置这个参数,缺省为68字节;
* @linktype:4字节, 链路类型, 一般都是1,类型说明见宏定义;
*
*/
struct pcap_file_head {
u8 magic[4];
u16 version_major;
u16 version_minor;
s32 thiszone;
u32 sigfigs;
u32 snaplen;
u32 linktype;
};
/*
* pcap_time_stamp - pcap包头中的时间戳结构体,由8字节组成
* @second:时间戳高位,精确到秒
* @microsecond:时间戳低位,精确到微秒
*
*/
struct pcap_time_stamp {
u32 second;
u32 microsecond;
};
/*
* pcap_packet_head: pcap包头结构体,数据包头由16字节组成.
* @timestamp:时间戳
* @caplen:当前数据区的长度,即抓取到的数据帧长度,由此可以得到下一个数据帧的位置。
* @len:离线数据长度:网络中实际数据帧的长度,一般不大于caplen,多数情况下和caplen数值相等
*
* Packet 数据,即 Packet(通常就是链路层的数据帧)具体内容,长度为caplen,这个长
* 度的后面,就是当前PCAP文件中存放的下一个Packet数据包,也就是说:PCAP文件里面
* 并没有规定捕获的Packet数据包之间有什么间隔字符串,下一组数据在文件中的起始位
* 置。我们需要靠第一个Packet包确定。
*
*/
struct pcap_packet_head {
struct pcap_time_stamp ts;
u32 caplen;
u32 len;
};
/*
* read_pcap_file_head - 读pcap(文件)头数据到结构体中。
* @pfd: 输入参数,读地址;
* @len: 输入参数,读数据长度;
* @pfh:输出参数,pcap(文件)头结构体;
* @counter: 输出参数,成功读入字节计数器;
*
* 读成功返回当前读地址,否则返回NULL;
* 解析读取完成后的数据(pcap_file_head)采用主机字节顺序。
*
*/
_my_pcap_ioptr read_pcap_file_head(_my_pcap_ioptr pfd, int len, struct pcap_file_head *pfh, int *counter);
/*
* read_pcap_packet_head - 读pcap数据包头到结构体中。
* @pfd: 输入参数,读地址;
* @len: 输入参数,读数据长度;
* @magic: 字节顺序标识;
* @pfh:输出参数,pcap(文件)头结构体;
* @counter: 输出参数,成功读入字节计数器;
*
* 读成功返回当前buf地址,否则返回NULL;
* 解析读取完成后的数据(pcap_packet_head)采用主机字节顺序。
*
*/
_my_pcap_ioptr read_pcap_packet_head(_my_pcap_ioptr pfd, int len, u8 magic[4], struct pcap_packet_head *pph, int *counter);
/*
* read_pcap_packet_data - 读pcap数据包数据
* @pfd: 输入参数,读地址;
* @ppd:输出参数,数据;
* @len: 输入参数,读数据长度;
* @counter: 输出参数,成功读入字节计数器;
*
* 读成功返回当前buf地址,否则返回NULL;ppd的空间大小必须不小于len值,否则失败。
*
*/
_my_pcap_ioptr read_pcap_packet_data(_my_pcap_ioptr pfd, u8* ppd, int len, int *counter);
/*
* write_pcap_file_head - 写pcap头到文件中
* @pfd: 输入参数,读地址;
* @pfh:输入参数,pcap(文件)头结构体;
* @count: 输出参数,成功写入的字节个数;
*
* 返回当前pfd指针,写失败返回NULL
*
*/
_my_pcap_ioptr write_pcap_file_head(_my_pcap_ioptr pfd, struct pcap_file_head *pfh, int *counter);
/*
* write_pcap_packet_head - 写pcap数据包头到文件中
* @pfd: 输入参数,读地址;
* @magic: 输入参数,字节顺序标识;
* @pph:输入参数,数据包头结构体
* @counter: 输出参数,成功写入字节计数器;
*
* 返回当前pfd指针,写失败返回NULL;
*
*/
_my_pcap_ioptr write_pcap_packet_head(_my_pcap_ioptr pfd, u8 magic[4], struct pcap_packet_head *pph, int* counter);
/*
* write_pcap_packet_data - 写pcap数据包数据到文件中
* @pfd: 输入参数,读地址;
* @ppd:输入参数,数据包数据;
* @ppdlen: 输入参数,数据包数据长度;
* @counter: 输出参数,成功写入字节计数器;
*
* 返回当前pfd指针,写失败返回NULL;
*
*/
_my_pcap_ioptr write_pcap_packet_data(_my_pcap_ioptr pfd, u8* ppd, int ppdlen, int* counter);
/*
* print_pcap_file_head - 打印pcap文件头数据
* @pfh:输入参数,pcap(文件)头结构体;
*
*/
void print_pcap_file_head(struct pcap_file_head *pfh);
/*
* print_pcap_packet_head - 打印pcap数据包头数据
* @pph:输入参数,pcap数据包头数据
*
*/
void print_pcap_packet_head(struct pcap_packet_head *pph);
/*
* print_pcap_packet_data - 打印pcap文件头数据
* @ppd:输入参数,pcap数据包数据;
* @ppdlen:输入参数,pcap数据包数据的长度;
*
*/
void print_pcap_packet_data(u8* ppd, int ppdlen);
#if defined (__cplusplus)
}
#endif /* defined (__cplusplus) */
#endif /* __INCLUDE_PCAP_FORMAT_H */
* pcap格式文件可由tcpdump或者wireshark生成,文件格式组成如下:
* file header
* packet header
* packet data
* packet header
* packet data
* ......
* 其中,file header为24字节,packet header为16字节,packet data为
* 变长数据,其长度由packet header中数据帧长度字段(caplen)决定。
*
* 本代码主要为了解决数字测试仪回放数字录波器的录波文件(pcap格式文
* 件)而编写的。
*
* 本代码支持win32平台和linux平台。
*
* Copyright,lizhi<ibox>
*
* 2012-10-10 V1.0 lizhi<QQ:252240557,msn:ddgooo@hotmail.com> created
*
*/
#ifndef __INCLUDE_PCAP_FORMAT_H
#define __INCLUDE_PCAP_FORMAT_H
/*
* 头文件
*/
#include "base_type.h"
#if defined (__cplusplus)
extern "C" {
#endif /* defined (__cplusplus) */
/*
* 宏开关 定义为文件读写
*/
#define PCAP_IOFILE
/*
* 宏定义文件的读写操作,可以根据需要改写该接口,如重定义
* 为网口的recv\send、串口r\w等。
*
* _my_read_pcap_bufn/_my_read_pcap_bufn/_my_check_pcap_ptr - pcap的读写操作以及句柄检查接口
* @pfd: 读写地址,可以为文件的fd、或者buffer地址等
* @buf: 缓冲区地址
* @count: 需要读写的字节数
*
*/
#if defined(PCAP_IOFILE)
typedef int _my_pcap_ioptr;
#define _my_read_pcap_bufn(pfd, buf, count) \
do { \
if (read((pfd), (buf), (count)) <= 0) { \
(pfd) = -1; \
} \
} while(0);
#define _my_write_pcap_bufn(pfd, buf, count) \
do { \
if (write((pfd), (buf), (count)) <= 0) { \
(pfd) = -1; \
} \
} while(0);
#define _my_check_pcap_ptr(pfd) \
(((pfd) != -1) && ((pfd) != 0))
#elif defined(PCAP_IOBUFFER)
typedef u8* _my_pcap_ioptr;
#define _my_read_pcap_bufn(pfd, buf, count) \
do { \
memcpy((buf), (pfd), (count)); \
(pfd) += (count); \
} while(0);
#define _my_write_pcap_bufn(pfd, buf, count) \
do { \
memcpy((pfd), (buf), (count)); \
(pfd) += (count); \
} while(0);
#define _my_check_pcap_ptr(pfd) \
(((pfd) != -1) && ((pfd) != 0))
#endif
/*
* 定义pcap文件格式中的头部信息(文件头部、数据包头部)的长度。
*
*/
#define PCAP_FILE_HEAD_SIZE 24
#define PCAP_PACKET_HEAD_SIZE 16
/*
* pcap文件版本号(主版本号、次版本号)定义。
*
*/
#define PCAP_FILE_VERSION_MAJOR 2
#define PCAP_FILE_VERSION_MINOR 4
/*
* pcap文件常用链路类型定义,最常用类型为1;基本描述:
* 0:BSD loopback devices, except for later OpenBSD
* 1:Ethernet, and Linux loopback devices
* 6:802.5 Token Ring
* 7:ARCnet
* 8:SLIP
* 9:PPP
* 10:FDDI
* 100:LLC/SNAP-encapsulated ATM
* 101:“raw IP”, with no link
* 102:BSD/OS SLIP
* 103:BSD/OS PPP
* 104:Cisco HDLC
* 105:802.11
* 108:later OpenBSD loopback devices (with the AF_value in network byte order)
* 113:special Linux “cooked” capture
* 114:LocalTalk
*
*/
#define PCAP_FILE_LINK_TYPE_BSD 0
#define PCAP_FILE_LINK_TYPE_ETHERNET 1
#define PCAP_FILE_LINK_TYPE_802D5 6
#define PCAP_FILE_LINK_TYPE_ARCNET 7
#define PCAP_FILE_LINK_TYPE_SLIP 8
#define PCAP_FILE_LINK_TYPE_PPP 9
#define PCAP_FILE_LINK_TYPE_FDDI 10
#define PCAP_FILE_LINK_TYPE_LLC_SNAPATM 100
#define PCAP_FILE_LINK_TYPE_RAW_IP 101
#define PCAP_FILE_LINK_TYPE_BSD_OSSLIP 102
#define PCAP_FILE_LINK_TYPE_BSD_OSPPP 103
#define PCAP_FILE_LINK_TYPE_CISCOHDLC 104
#define PCAP_FILE_LINK_TYPE_802D11 105
#define PCAP_FILE_LINK_TYPE_OPENBSD 108
#define PCAP_FILE_LINK_TYPE_LINUXCOOKED 113
#define PCAP_FILE_LINK_TYPE_LOCALTALK 114
/*
* pcap_file_head - pcap(文件)头结构体,由24字节组成.
* @magic: 4字节, 用来识别文件自己和字节顺序。0xa1b2c3d4用来表示按照原来的顺序读取,
* 0xd4c3b2a1表示下面的字节都要交换顺序读取。一般,我们使用0xa1b2c3d4;
* 保持网络字节顺序;
* @major: 2字节, 主版本号;
* @minor: 2字节, 次版本号;
* @thiszone:4字节, 时区。GMT和本地时间的相差,用秒来表示。如果本地的时区是GMT,那么这
* 个值就设置为0.这个值一般也设置为0
* @sigfigs: 4字节, 精确时间戳,并未使用,目前全为0;
* @snaplen: 4字节, 抓包最大长度,如果要抓全,设为0x0000ffff(65535),tcpdump -s 0就
* 是设置这个参数,缺省为68字节;
* @linktype:4字节, 链路类型, 一般都是1,类型说明见宏定义;
*
*/
struct pcap_file_head {
u8 magic[4];
u16 version_major;
u16 version_minor;
s32 thiszone;
u32 sigfigs;
u32 snaplen;
u32 linktype;
};
/*
* pcap_time_stamp - pcap包头中的时间戳结构体,由8字节组成
* @second:时间戳高位,精确到秒
* @microsecond:时间戳低位,精确到微秒
*
*/
struct pcap_time_stamp {
u32 second;
u32 microsecond;
};
/*
* pcap_packet_head: pcap包头结构体,数据包头由16字节组成.
* @timestamp:时间戳
* @caplen:当前数据区的长度,即抓取到的数据帧长度,由此可以得到下一个数据帧的位置。
* @len:离线数据长度:网络中实际数据帧的长度,一般不大于caplen,多数情况下和caplen数值相等
*
* Packet 数据,即 Packet(通常就是链路层的数据帧)具体内容,长度为caplen,这个长
* 度的后面,就是当前PCAP文件中存放的下一个Packet数据包,也就是说:PCAP文件里面
* 并没有规定捕获的Packet数据包之间有什么间隔字符串,下一组数据在文件中的起始位
* 置。我们需要靠第一个Packet包确定。
*
*/
struct pcap_packet_head {
struct pcap_time_stamp ts;
u32 caplen;
u32 len;
};
/*
* read_pcap_file_head - 读pcap(文件)头数据到结构体中。
* @pfd: 输入参数,读地址;
* @len: 输入参数,读数据长度;
* @pfh:输出参数,pcap(文件)头结构体;
* @counter: 输出参数,成功读入字节计数器;
*
* 读成功返回当前读地址,否则返回NULL;
* 解析读取完成后的数据(pcap_file_head)采用主机字节顺序。
*
*/
_my_pcap_ioptr read_pcap_file_head(_my_pcap_ioptr pfd, int len, struct pcap_file_head *pfh, int *counter);
/*
* read_pcap_packet_head - 读pcap数据包头到结构体中。
* @pfd: 输入参数,读地址;
* @len: 输入参数,读数据长度;
* @magic: 字节顺序标识;
* @pfh:输出参数,pcap(文件)头结构体;
* @counter: 输出参数,成功读入字节计数器;
*
* 读成功返回当前buf地址,否则返回NULL;
* 解析读取完成后的数据(pcap_packet_head)采用主机字节顺序。
*
*/
_my_pcap_ioptr read_pcap_packet_head(_my_pcap_ioptr pfd, int len, u8 magic[4], struct pcap_packet_head *pph, int *counter);
/*
* read_pcap_packet_data - 读pcap数据包数据
* @pfd: 输入参数,读地址;
* @ppd:输出参数,数据;
* @len: 输入参数,读数据长度;
* @counter: 输出参数,成功读入字节计数器;
*
* 读成功返回当前buf地址,否则返回NULL;ppd的空间大小必须不小于len值,否则失败。
*
*/
_my_pcap_ioptr read_pcap_packet_data(_my_pcap_ioptr pfd, u8* ppd, int len, int *counter);
/*
* write_pcap_file_head - 写pcap头到文件中
* @pfd: 输入参数,读地址;
* @pfh:输入参数,pcap(文件)头结构体;
* @count: 输出参数,成功写入的字节个数;
*
* 返回当前pfd指针,写失败返回NULL
*
*/
_my_pcap_ioptr write_pcap_file_head(_my_pcap_ioptr pfd, struct pcap_file_head *pfh, int *counter);
/*
* write_pcap_packet_head - 写pcap数据包头到文件中
* @pfd: 输入参数,读地址;
* @magic: 输入参数,字节顺序标识;
* @pph:输入参数,数据包头结构体
* @counter: 输出参数,成功写入字节计数器;
*
* 返回当前pfd指针,写失败返回NULL;
*
*/
_my_pcap_ioptr write_pcap_packet_head(_my_pcap_ioptr pfd, u8 magic[4], struct pcap_packet_head *pph, int* counter);
/*
* write_pcap_packet_data - 写pcap数据包数据到文件中
* @pfd: 输入参数,读地址;
* @ppd:输入参数,数据包数据;
* @ppdlen: 输入参数,数据包数据长度;
* @counter: 输出参数,成功写入字节计数器;
*
* 返回当前pfd指针,写失败返回NULL;
*
*/
_my_pcap_ioptr write_pcap_packet_data(_my_pcap_ioptr pfd, u8* ppd, int ppdlen, int* counter);
/*
* print_pcap_file_head - 打印pcap文件头数据
* @pfh:输入参数,pcap(文件)头结构体;
*
*/
void print_pcap_file_head(struct pcap_file_head *pfh);
/*
* print_pcap_packet_head - 打印pcap数据包头数据
* @pph:输入参数,pcap数据包头数据
*
*/
void print_pcap_packet_head(struct pcap_packet_head *pph);
/*
* print_pcap_packet_data - 打印pcap文件头数据
* @ppd:输入参数,pcap数据包数据;
* @ppdlen:输入参数,pcap数据包数据的长度;
*
*/
void print_pcap_packet_data(u8* ppd, int ppdlen);
#if defined (__cplusplus)
}
#endif /* defined (__cplusplus) */
#endif /* __INCLUDE_PCAP_FORMAT_H */
c文件pcap_format.c代码:
/*
* 分析解析pcap文件协议格式。
*
* 本代码支持win32平台和linux平台。
*
* Copyright,lizhi[ibox]
*
* 2012-10-10 V1.0 lizhi<QQ:252240557,msn:ddgooo@hotmail.com> created
*
*/
/*
* 头文件
*/
#include "base_type.h"
#include "base_include.h"
#include "base_debug.h"
#include "base_endian.h"
#include "base_function.h"
#include "pcap_format.h"
/*
* 测试宏开关,pcap文件demo
*/
/*
#define PCAP_CONSOLE_DEMO
// */
/*
* _my_read_pcap_data/_my_write_pcap_data - 读取/写入并且转换pcap数据。
* @src: 读写地址,为buffer地址;
* @data: 读取/写入的数据;
* @count: 需要读取/写入的字节个数;
* @counter: 读取/写入的字节计数器;
*
*/
#define _my_read_pcap_data(src, data, count, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
_my_read_pcap_bufn((src), (data), (count)); \
(counter) += (count); \
} \
} while(0);
#define _my_write_pcap_data(src, data, count, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
_my_write_pcap_bufn((src), (data), (count)); \
(counter) +=(count); \
} \
} while(0);
/*
* _my_read_pcap_to_host16/_my_read_pcap_to_host32 - 读取并且转换pcap数据。
* @src: 读写地址,为buffer地址;
* @data: 读取的数据;
* @magic: 顺序标识,来自pcap文件中的magic标识;
* @counter: 读取的字节计数器;
*
* 从pcap读取2字节或者4字节数据,并且根据magic顺序转换pcap数据到host顺序。
*
*/
#define _my_read_pcap_to_host16(src, data, magic, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
_my_read_pcap_bufn((src), &(data), 2); \
if (0xA1 == *(magic)) { \
data = _my_btoh16(data); \
} else { \
data = _my_ltoh16(data); \
} \
(counter) += 2; \
} \
} while(0);
#define _my_read_pcap_to_host32(src, data, magic, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
_my_read_pcap_bufn((src), &(data), 4); \
if (0xA1 == *(magic)) { \
data = _my_btoh32(data); \
} else { \
data = _my_ltoh32(data); \
} \
(counter) += 4; \
} \
} while(0);
/*
* _my_write_host_to_pcap16/_my_write_host_to_pcap32 - 转换pcap数据并且写入。
* @src: 写入地址,为buffer地址;
* @data: 写入的数据;
* @magic: 顺序标识,来自pcap文件中的magic标识;
* @counter: 写入的字节计数器;
*
* 根据magic顺序转换pcap数据到host顺序,并且写入2字节或者4字节pcap数据。
*
*/
#define _my_write_host_to_pcap16(src, data, magic, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
u16 temp = data; \
if (0xA1 == *(magic)) { \
temp = _my_htob16(data); \
} else { \
temp = _my_htol16(data); \
} \
_my_write_pcap_bufn((src), &(temp), 2); \
(counter) += 2; \
} \
} while(0);
#define _my_write_host_to_pcap32(src, data, magic, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
u32 temp = data; \
if (0xA1 == *(magic)) { \
temp = _my_htob32(data); \
} else { \
temp = _my_htol32(data); \
} \
_my_write_pcap_bufn((src), &(temp), 4); \
(counter) += 4; \
} \
} while(0);
/*
* read_pcap_file_head - 读pcap(文件)头数据到结构体中。
* @pfd: 输入参数,读地址;
* @len: 输入参数,数据缓冲区长度;
* @pfh:输出参数,pcap(文件)头结构体;
* @counter: 输出参数,读取的字节计数器;
*
* 读成功返回当前读地址,否则返回NULL;
* 解析读取完成后的数据(pcap_file_head)采用主机字节顺序。
*
*/
_my_pcap_ioptr read_pcap_file_head(_my_pcap_ioptr pfd, int len, struct pcap_file_head *pfh, int *counter)
{
int oldnum = 0;
_my_pcap_ioptr ptr = pfd;
if (ptr && pfh && (PCAP_FILE_HEAD_SIZE <= len) && counter) {
oldnum = (*counter);
_my_read_pcap_data(ptr, pfh->magic, 4, *counter);
_my_read_pcap_to_host16(ptr, pfh->version_major, pfh->magic, *counter);
_my_read_pcap_to_host16(ptr, pfh->version_minor, pfh->magic, *counter);
_my_read_pcap_to_host32(ptr, pfh->thiszone, pfh->magic, *counter);
_my_read_pcap_to_host32(ptr, pfh->sigfigs, pfh->magic, *counter);
_my_read_pcap_to_host32(ptr, pfh->snaplen, pfh->magic, *counter);
_my_read_pcap_to_host32(ptr, pfh->linktype, pfh->magic, *counter);
if (PCAP_FILE_HEAD_SIZE == ((*counter) - oldnum)) {
return ptr;
}
}
return 0;
}
/*
* read_pcap_packet_head - 读pcap数据包头到结构体中。
* @pfd: 输入参数,读地址;
* @len: 输入参数,读数据长度;
* @magic: 字节顺序标识;
* @pfh:输出参数,pcap(文件)头结构体;
* @counter: 输出参数,读取的字节计数器;
*
* 读成功返回当前buf地址,否则返回NULL;
* 解析读取完成后的数据(pcap_packet_head)采用主机字节顺序。
*
*/
_my_pcap_ioptr read_pcap_packet_head(_my_pcap_ioptr pfd, int len, u8 magic[4], struct pcap_packet_head *pph, int *counter)
{
int oldnum = 0;
_my_pcap_ioptr ptr = pfd;
if (ptr && pph && (PCAP_PACKET_HEAD_SIZE <= len) && counter) {
oldnum = (*counter);
_my_read_pcap_to_host32(ptr, pph->ts.second, magic, *counter);
_my_read_pcap_to_host32(ptr, pph->ts.microsecond, magic, *counter);
_my_read_pcap_to_host32(ptr, pph->caplen, magic, *counter);
_my_read_pcap_to_host32(ptr, pph->len, magic, *counter);
if (PCAP_PACKET_HEAD_SIZE == ((*counter) - oldnum)) {
return ptr;
}
}
return 0;
}
/*
* read_pcap_packet_data - 读pcap数据包数据
* @pfd: 输入参数,读地址;
* @ppd:输出参数,数据;
* @len: 输入参数,读数据长度;
* @counter: 输出参数,读取的字节计数器;
*
* 读成功返回当前buf地址,否则返回NULL;ppd的空间大小必须不小于len值,否则失败。
*
*/
_my_pcap_ioptr read_pcap_packet_data(_my_pcap_ioptr pfd, u8* ppd, int len, int *counter)
{
_my_pcap_ioptr ptr = pfd;
if ( ptr && ppd && (0 <= len) && counter) {
_my_read_pcap_data(ptr, ppd, len, *counter);
return ptr;
}
return 0;
}
/*
* write_pcap_file_head - 写pcap头到文件中
* @pfd: 输入参数,读地址;
* @pfh:输入参数,pcap(文件)头结构体;
* @counter: 输出参数,成功写入字节计数器;
*
* 返回当前pfd指针,写失败返回NULL
*
*/
_my_pcap_ioptr write_pcap_file_head(_my_pcap_ioptr pfd, struct pcap_file_head *pfh, int *counter)
{
u16 temp = 0;
int oldnum = 0;
_my_pcap_ioptr ptr = pfd;
if (ptr && pfh && counter) {
oldnum = (*counter);
_my_write_pcap_data(ptr, pfh->magic, 4, *counter);
_my_write_host_to_pcap16(ptr, pfh->version_major, pfh->magic, *counter);
_my_write_host_to_pcap16(ptr, pfh->version_minor, pfh->magic, *counter);
_my_write_host_to_pcap32(ptr, pfh->thiszone, pfh->magic, *counter);
_my_write_host_to_pcap32(ptr, pfh->sigfigs, pfh->magic, *counter);
_my_write_host_to_pcap32(ptr, pfh->snaplen, pfh->magic, *counter);
_my_write_host_to_pcap32(ptr, pfh->linktype, pfh->magic, *counter);
if (PCAP_FILE_HEAD_SIZE == ((*counter) - oldnum)) {
return ptr;
}
}
return 0;
}
/*
* write_pcap_packet_head - 写pcap数据包头到文件中
* @pfd: 输入参数,读地址;
* @magic: 输入参数,字节顺序标识;
* @pph:输入参数,数据包头结构体
* @counter: 输出参数,成功写入字节计数器;
*
* 返回当前pfd指针,写失败返回NULL;
*
*/
_my_pcap_ioptr write_pcap_packet_head(_my_pcap_ioptr pfd, u8 magic[4], struct pcap_packet_head *pph, int* counter)
{
int oldnum = 0;
_my_pcap_ioptr ptr = pfd;
if (ptr && pph && counter) {
oldnum = (*counter);
_my_write_host_to_pcap32(ptr, pph->ts.second, magic, *counter);
_my_write_host_to_pcap32(ptr, pph->ts.microsecond, magic, *counter);
_my_write_host_to_pcap32(ptr, pph->caplen, magic, *counter);
_my_write_host_to_pcap32(ptr, pph->len, magic, *counter);
if (PCAP_PACKET_HEAD_SIZE == ((*counter) - oldnum)) {
return ptr;
}
}
return 0;
}
/*
* write_pcap_packet_data - 写pcap数据包数据到文件中
* @pfd: 输入参数,读地址;
* @ppd:输入参数,数据包数据;
* @ppdlen: 输入参数,数据包数据长度;
* @counter: 输出参数,成功写入字节计数器;
*
* 返回当前pfd指针,写失败返回NULL;
*
*/
_my_pcap_ioptr write_pcap_packet_data(_my_pcap_ioptr pfd, u8* ppd, int ppdlen, int* counter)
{
_my_pcap_ioptr ptr = pfd;
if ( ptr && ppd && counter && (ppdlen > 0)) {
_my_write_pcap_data(ptr, ppd, ppdlen, *counter);
return ptr;
}
return 0;
}
/*
* print_pcap_file_head - 打印pcap文件头数据
* @pfh:输入参数,pcap(文件)头结构体;
*
*/
void print_pcap_file_head(struct pcap_file_head *pfh)
{
if ( pfh ) {
_my_printf("=====================\n");
_my_printf("magic:%02x%02x%02x%02x\n", pfh->magic[0], pfh->magic[1], pfh->magic[2], pfh->magic[3]);
_my_printf("version_major:%u [0x%08x]\n", pfh->version_major, pfh->version_major);
_my_printf("version_minor:%u [0x%08x]\n", pfh->version_minor, pfh->version_minor);
_my_printf("thiszone:%d [0x%08x]\n", pfh->thiszone, (u32)(pfh->thiszone));
_my_printf("sigfigs:%u [0x%08x]\n", pfh->sigfigs, pfh->sigfigs);
_my_printf("snaplen:%u [0x%08x]\n", pfh->snaplen, pfh->snaplen);
_my_printf("linktype:%u [0x%08x]\n", pfh->linktype, pfh->linktype);
_my_printf("=====================\n");
}
}
/*
* print_pcap_packet_head - 打印pcap数据包头数据
* @pph:输入参数,pcap数据包头数据
*
*/
void print_pcap_packet_head(struct pcap_packet_head *pph)
{
if ( pph ) {
_my_printf("=====================\n");
_my_printf("ts.second:%u [0x%08x]\n", pph->ts.second, pph->ts.second);
_my_printf("ts.microsecond:%u [0x%08x]\n", pph->ts.microsecond, pph->ts.microsecond);
_my_printf("caplen:%u [0x%08x]\n", pph->caplen, pph->caplen);
_my_printf("len:%u [0x%08x]\n", pph->len, pph->len);
_my_printf("=====================\n");
}
}
/*
* print_pcap_packet_data - 打印pcap文件头数据
* @ppd:输入参数,pcap数据包数据;
* @ppdlen:输入参数,pcap数据包数据的长度;
*
*/
void print_pcap_packet_data(u8* ppd, int ppdlen)
{
u32 ipos = 0;
if ( ppd ) {
_my_printf("\n====ppd:0x%x,len:%u=====", (int)ppd, ppdlen);
for (ipos=0; ipos < ppdlen; ipos++) {
if ((ipos % 16) ==0) {
_my_printf("\n");
}
_my_printf("%02X ",(int)(*(ppd + ipos)));
}
_my_printf("\n=====================");
}
}
#ifdef PCAP_CONSOLE_DEMO
/*
* _my_pcap_openrb/_my_pcap_openwb/_my_pcap_openab/_my_pcap_close
* - 可以根据需要改写该接口,如重定义为网口的recv\send、串口r\w等
* @pfd: 文件地址、缓冲区地址、或者socket地址等
* @str: 文件路径或者联机ip或者串口地址或者共享内存名称
*
*/
#ifdef PCAP_IOFILE
#define _my_pcap_openrb(str) (open((str), O_RDONLY | O_BINARY, S_IWRITE | S_IREAD))
#define _my_pcap_openwb(str) (open((str), O_CREAT | O_RDWR | O_BINARY, S_IWRITE | S_IREAD))
#define _my_pcap_openab(str) (open((str), O_CREAT | O_APPEND | O_RDWR | O_BINARY, S_IWRITE | S_IREAD))
#define _my_pcap_close(pfd) (close(pfd))
#else /* 定义其他的io*/
#endif
/*
* pcap_test_demo - 测试函数
* @pcap_pathname: pcap文件路径
* @packet_pathname: pcaket文件路径
*
*/
void pcap_test_demo(const char* pcap_pathname, const char* packet_pathname)
{
int read_count = 0;
int pckt_count = 0;
u8* ppd = 0;
struct pcap_file_head pfh;
struct pcap_packet_head pph;
char chget;
_my_pcap_ioptr fdpcap = 0;
_my_pcap_ioptr fdpckt = 0;
memset(&pfh, 0, sizeof(struct pcap_file_head));
memset(&pph, 0, sizeof(struct pcap_packet_head));
pckt_count = 0;
read_count = 0;
fdpcap = _my_pcap_openrb(pcap_pathname);
fdpckt = _my_pcap_openab(packet_pathname);
if ( fdpcap ) {
fdpcap = read_pcap_file_head(fdpcap, PCAP_FILE_HEAD_SIZE, &pfh, &read_count);
if (0 != fdpcap) {
_my_printf("press [s] to break, any other keys to show pcap file header data.....\n");
chget = getchar();
if (chget == 's') {
return;
}
print_pcap_file_head(&pfh);
fdpckt = write_pcap_file_head(fdpckt, &pfh, &pckt_count);
while (!(chget == 's')) {
_my_printf("press [s] to break, any other keys to continue showing pcap packet header data......\n");
chget = getchar();
if (chget == 's') {
break;
}
fdpcap = read_pcap_packet_head(fdpcap, PCAP_PACKET_HEAD_SIZE, pfh.magic, &pph, &read_count);
if (0 != fdpcap) {
_my_printf("pcap data packet header count %d\n", pckt_count);
print_pcap_packet_head(&pph);
fdpckt = write_pcap_packet_head(fdpckt, pfh.magic, &pph, &pckt_count);
_my_printf("press [s] to break, any other keys to continue showing pcap packet content data.......\n");
chget = getchar();
if (chget == 's') {
break;
}
ppd = (u8 *)_my_buf_malloc((size_t)(pph.caplen));
fdpcap = read_pcap_packet_data(fdpcap, ppd, pph.caplen, &read_count);
if ( 0 != fdpcap) {
print_pcap_packet_data(ppd, pph.caplen);
fdpckt = write_pcap_packet_data(fdpckt, ppd, pph.caplen, &pckt_count);
free(ppd);
ppd = 0;
continue;
}
_my_buf_free(ppd);
ppd = 0;
}
break;
}
}
_my_pcap_close(fdpcap);
}
}
/*
* main - 测试main函数
*
*/
int main(int argc, char* argv[])
{
char pcap_pathname[255];
char packet_pathname[255];
pcap_test_demo(
"D:/09160016",
"D:/09160016.dat"
);
return 0;
}
#endif /* PCAP_CONSOLE_DEMO */
* 分析解析pcap文件协议格式。
*
* 本代码支持win32平台和linux平台。
*
* Copyright,lizhi[ibox]
*
* 2012-10-10 V1.0 lizhi<QQ:252240557,msn:ddgooo@hotmail.com> created
*
*/
/*
* 头文件
*/
#include "base_type.h"
#include "base_include.h"
#include "base_debug.h"
#include "base_endian.h"
#include "base_function.h"
#include "pcap_format.h"
/*
* 测试宏开关,pcap文件demo
*/
/*
#define PCAP_CONSOLE_DEMO
// */
/*
* _my_read_pcap_data/_my_write_pcap_data - 读取/写入并且转换pcap数据。
* @src: 读写地址,为buffer地址;
* @data: 读取/写入的数据;
* @count: 需要读取/写入的字节个数;
* @counter: 读取/写入的字节计数器;
*
*/
#define _my_read_pcap_data(src, data, count, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
_my_read_pcap_bufn((src), (data), (count)); \
(counter) += (count); \
} \
} while(0);
#define _my_write_pcap_data(src, data, count, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
_my_write_pcap_bufn((src), (data), (count)); \
(counter) +=(count); \
} \
} while(0);
/*
* _my_read_pcap_to_host16/_my_read_pcap_to_host32 - 读取并且转换pcap数据。
* @src: 读写地址,为buffer地址;
* @data: 读取的数据;
* @magic: 顺序标识,来自pcap文件中的magic标识;
* @counter: 读取的字节计数器;
*
* 从pcap读取2字节或者4字节数据,并且根据magic顺序转换pcap数据到host顺序。
*
*/
#define _my_read_pcap_to_host16(src, data, magic, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
_my_read_pcap_bufn((src), &(data), 2); \
if (0xA1 == *(magic)) { \
data = _my_btoh16(data); \
} else { \
data = _my_ltoh16(data); \
} \
(counter) += 2; \
} \
} while(0);
#define _my_read_pcap_to_host32(src, data, magic, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
_my_read_pcap_bufn((src), &(data), 4); \
if (0xA1 == *(magic)) { \
data = _my_btoh32(data); \
} else { \
data = _my_ltoh32(data); \
} \
(counter) += 4; \
} \
} while(0);
/*
* _my_write_host_to_pcap16/_my_write_host_to_pcap32 - 转换pcap数据并且写入。
* @src: 写入地址,为buffer地址;
* @data: 写入的数据;
* @magic: 顺序标识,来自pcap文件中的magic标识;
* @counter: 写入的字节计数器;
*
* 根据magic顺序转换pcap数据到host顺序,并且写入2字节或者4字节pcap数据。
*
*/
#define _my_write_host_to_pcap16(src, data, magic, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
u16 temp = data; \
if (0xA1 == *(magic)) { \
temp = _my_htob16(data); \
} else { \
temp = _my_htol16(data); \
} \
_my_write_pcap_bufn((src), &(temp), 2); \
(counter) += 2; \
} \
} while(0);
#define _my_write_host_to_pcap32(src, data, magic, counter) \
do { \
if (_my_check_pcap_ptr(src)) { \
u32 temp = data; \
if (0xA1 == *(magic)) { \
temp = _my_htob32(data); \
} else { \
temp = _my_htol32(data); \
} \
_my_write_pcap_bufn((src), &(temp), 4); \
(counter) += 4; \
} \
} while(0);
/*
* read_pcap_file_head - 读pcap(文件)头数据到结构体中。
* @pfd: 输入参数,读地址;
* @len: 输入参数,数据缓冲区长度;
* @pfh:输出参数,pcap(文件)头结构体;
* @counter: 输出参数,读取的字节计数器;
*
* 读成功返回当前读地址,否则返回NULL;
* 解析读取完成后的数据(pcap_file_head)采用主机字节顺序。
*
*/
_my_pcap_ioptr read_pcap_file_head(_my_pcap_ioptr pfd, int len, struct pcap_file_head *pfh, int *counter)
{
int oldnum = 0;
_my_pcap_ioptr ptr = pfd;
if (ptr && pfh && (PCAP_FILE_HEAD_SIZE <= len) && counter) {
oldnum = (*counter);
_my_read_pcap_data(ptr, pfh->magic, 4, *counter);
_my_read_pcap_to_host16(ptr, pfh->version_major, pfh->magic, *counter);
_my_read_pcap_to_host16(ptr, pfh->version_minor, pfh->magic, *counter);
_my_read_pcap_to_host32(ptr, pfh->thiszone, pfh->magic, *counter);
_my_read_pcap_to_host32(ptr, pfh->sigfigs, pfh->magic, *counter);
_my_read_pcap_to_host32(ptr, pfh->snaplen, pfh->magic, *counter);
_my_read_pcap_to_host32(ptr, pfh->linktype, pfh->magic, *counter);
if (PCAP_FILE_HEAD_SIZE == ((*counter) - oldnum)) {
return ptr;
}
}
return 0;
}
/*
* read_pcap_packet_head - 读pcap数据包头到结构体中。
* @pfd: 输入参数,读地址;
* @len: 输入参数,读数据长度;
* @magic: 字节顺序标识;
* @pfh:输出参数,pcap(文件)头结构体;
* @counter: 输出参数,读取的字节计数器;
*
* 读成功返回当前buf地址,否则返回NULL;
* 解析读取完成后的数据(pcap_packet_head)采用主机字节顺序。
*
*/
_my_pcap_ioptr read_pcap_packet_head(_my_pcap_ioptr pfd, int len, u8 magic[4], struct pcap_packet_head *pph, int *counter)
{
int oldnum = 0;
_my_pcap_ioptr ptr = pfd;
if (ptr && pph && (PCAP_PACKET_HEAD_SIZE <= len) && counter) {
oldnum = (*counter);
_my_read_pcap_to_host32(ptr, pph->ts.second, magic, *counter);
_my_read_pcap_to_host32(ptr, pph->ts.microsecond, magic, *counter);
_my_read_pcap_to_host32(ptr, pph->caplen, magic, *counter);
_my_read_pcap_to_host32(ptr, pph->len, magic, *counter);
if (PCAP_PACKET_HEAD_SIZE == ((*counter) - oldnum)) {
return ptr;
}
}
return 0;
}
/*
* read_pcap_packet_data - 读pcap数据包数据
* @pfd: 输入参数,读地址;
* @ppd:输出参数,数据;
* @len: 输入参数,读数据长度;
* @counter: 输出参数,读取的字节计数器;
*
* 读成功返回当前buf地址,否则返回NULL;ppd的空间大小必须不小于len值,否则失败。
*
*/
_my_pcap_ioptr read_pcap_packet_data(_my_pcap_ioptr pfd, u8* ppd, int len, int *counter)
{
_my_pcap_ioptr ptr = pfd;
if ( ptr && ppd && (0 <= len) && counter) {
_my_read_pcap_data(ptr, ppd, len, *counter);
return ptr;
}
return 0;
}
/*
* write_pcap_file_head - 写pcap头到文件中
* @pfd: 输入参数,读地址;
* @pfh:输入参数,pcap(文件)头结构体;
* @counter: 输出参数,成功写入字节计数器;
*
* 返回当前pfd指针,写失败返回NULL
*
*/
_my_pcap_ioptr write_pcap_file_head(_my_pcap_ioptr pfd, struct pcap_file_head *pfh, int *counter)
{
u16 temp = 0;
int oldnum = 0;
_my_pcap_ioptr ptr = pfd;
if (ptr && pfh && counter) {
oldnum = (*counter);
_my_write_pcap_data(ptr, pfh->magic, 4, *counter);
_my_write_host_to_pcap16(ptr, pfh->version_major, pfh->magic, *counter);
_my_write_host_to_pcap16(ptr, pfh->version_minor, pfh->magic, *counter);
_my_write_host_to_pcap32(ptr, pfh->thiszone, pfh->magic, *counter);
_my_write_host_to_pcap32(ptr, pfh->sigfigs, pfh->magic, *counter);
_my_write_host_to_pcap32(ptr, pfh->snaplen, pfh->magic, *counter);
_my_write_host_to_pcap32(ptr, pfh->linktype, pfh->magic, *counter);
if (PCAP_FILE_HEAD_SIZE == ((*counter) - oldnum)) {
return ptr;
}
}
return 0;
}
/*
* write_pcap_packet_head - 写pcap数据包头到文件中
* @pfd: 输入参数,读地址;
* @magic: 输入参数,字节顺序标识;
* @pph:输入参数,数据包头结构体
* @counter: 输出参数,成功写入字节计数器;
*
* 返回当前pfd指针,写失败返回NULL;
*
*/
_my_pcap_ioptr write_pcap_packet_head(_my_pcap_ioptr pfd, u8 magic[4], struct pcap_packet_head *pph, int* counter)
{
int oldnum = 0;
_my_pcap_ioptr ptr = pfd;
if (ptr && pph && counter) {
oldnum = (*counter);
_my_write_host_to_pcap32(ptr, pph->ts.second, magic, *counter);
_my_write_host_to_pcap32(ptr, pph->ts.microsecond, magic, *counter);
_my_write_host_to_pcap32(ptr, pph->caplen, magic, *counter);
_my_write_host_to_pcap32(ptr, pph->len, magic, *counter);
if (PCAP_PACKET_HEAD_SIZE == ((*counter) - oldnum)) {
return ptr;
}
}
return 0;
}
/*
* write_pcap_packet_data - 写pcap数据包数据到文件中
* @pfd: 输入参数,读地址;
* @ppd:输入参数,数据包数据;
* @ppdlen: 输入参数,数据包数据长度;
* @counter: 输出参数,成功写入字节计数器;
*
* 返回当前pfd指针,写失败返回NULL;
*
*/
_my_pcap_ioptr write_pcap_packet_data(_my_pcap_ioptr pfd, u8* ppd, int ppdlen, int* counter)
{
_my_pcap_ioptr ptr = pfd;
if ( ptr && ppd && counter && (ppdlen > 0)) {
_my_write_pcap_data(ptr, ppd, ppdlen, *counter);
return ptr;
}
return 0;
}
/*
* print_pcap_file_head - 打印pcap文件头数据
* @pfh:输入参数,pcap(文件)头结构体;
*
*/
void print_pcap_file_head(struct pcap_file_head *pfh)
{
if ( pfh ) {
_my_printf("=====================\n");
_my_printf("magic:%02x%02x%02x%02x\n", pfh->magic[0], pfh->magic[1], pfh->magic[2], pfh->magic[3]);
_my_printf("version_major:%u [0x%08x]\n", pfh->version_major, pfh->version_major);
_my_printf("version_minor:%u [0x%08x]\n", pfh->version_minor, pfh->version_minor);
_my_printf("thiszone:%d [0x%08x]\n", pfh->thiszone, (u32)(pfh->thiszone));
_my_printf("sigfigs:%u [0x%08x]\n", pfh->sigfigs, pfh->sigfigs);
_my_printf("snaplen:%u [0x%08x]\n", pfh->snaplen, pfh->snaplen);
_my_printf("linktype:%u [0x%08x]\n", pfh->linktype, pfh->linktype);
_my_printf("=====================\n");
}
}
/*
* print_pcap_packet_head - 打印pcap数据包头数据
* @pph:输入参数,pcap数据包头数据
*
*/
void print_pcap_packet_head(struct pcap_packet_head *pph)
{
if ( pph ) {
_my_printf("=====================\n");
_my_printf("ts.second:%u [0x%08x]\n", pph->ts.second, pph->ts.second);
_my_printf("ts.microsecond:%u [0x%08x]\n", pph->ts.microsecond, pph->ts.microsecond);
_my_printf("caplen:%u [0x%08x]\n", pph->caplen, pph->caplen);
_my_printf("len:%u [0x%08x]\n", pph->len, pph->len);
_my_printf("=====================\n");
}
}
/*
* print_pcap_packet_data - 打印pcap文件头数据
* @ppd:输入参数,pcap数据包数据;
* @ppdlen:输入参数,pcap数据包数据的长度;
*
*/
void print_pcap_packet_data(u8* ppd, int ppdlen)
{
u32 ipos = 0;
if ( ppd ) {
_my_printf("\n====ppd:0x%x,len:%u=====", (int)ppd, ppdlen);
for (ipos=0; ipos < ppdlen; ipos++) {
if ((ipos % 16) ==0) {
_my_printf("\n");
}
_my_printf("%02X ",(int)(*(ppd + ipos)));
}
_my_printf("\n=====================");
}
}
#ifdef PCAP_CONSOLE_DEMO
/*
* _my_pcap_openrb/_my_pcap_openwb/_my_pcap_openab/_my_pcap_close
* - 可以根据需要改写该接口,如重定义为网口的recv\send、串口r\w等
* @pfd: 文件地址、缓冲区地址、或者socket地址等
* @str: 文件路径或者联机ip或者串口地址或者共享内存名称
*
*/
#ifdef PCAP_IOFILE
#define _my_pcap_openrb(str) (open((str), O_RDONLY | O_BINARY, S_IWRITE | S_IREAD))
#define _my_pcap_openwb(str) (open((str), O_CREAT | O_RDWR | O_BINARY, S_IWRITE | S_IREAD))
#define _my_pcap_openab(str) (open((str), O_CREAT | O_APPEND | O_RDWR | O_BINARY, S_IWRITE | S_IREAD))
#define _my_pcap_close(pfd) (close(pfd))
#else /* 定义其他的io*/
#endif
/*
* pcap_test_demo - 测试函数
* @pcap_pathname: pcap文件路径
* @packet_pathname: pcaket文件路径
*
*/
void pcap_test_demo(const char* pcap_pathname, const char* packet_pathname)
{
int read_count = 0;
int pckt_count = 0;
u8* ppd = 0;
struct pcap_file_head pfh;
struct pcap_packet_head pph;
char chget;
_my_pcap_ioptr fdpcap = 0;
_my_pcap_ioptr fdpckt = 0;
memset(&pfh, 0, sizeof(struct pcap_file_head));
memset(&pph, 0, sizeof(struct pcap_packet_head));
pckt_count = 0;
read_count = 0;
fdpcap = _my_pcap_openrb(pcap_pathname);
fdpckt = _my_pcap_openab(packet_pathname);
if ( fdpcap ) {
fdpcap = read_pcap_file_head(fdpcap, PCAP_FILE_HEAD_SIZE, &pfh, &read_count);
if (0 != fdpcap) {
_my_printf("press [s] to break, any other keys to show pcap file header data.....\n");
chget = getchar();
if (chget == 's') {
return;
}
print_pcap_file_head(&pfh);
fdpckt = write_pcap_file_head(fdpckt, &pfh, &pckt_count);
while (!(chget == 's')) {
_my_printf("press [s] to break, any other keys to continue showing pcap packet header data......\n");
chget = getchar();
if (chget == 's') {
break;
}
fdpcap = read_pcap_packet_head(fdpcap, PCAP_PACKET_HEAD_SIZE, pfh.magic, &pph, &read_count);
if (0 != fdpcap) {
_my_printf("pcap data packet header count %d\n", pckt_count);
print_pcap_packet_head(&pph);
fdpckt = write_pcap_packet_head(fdpckt, pfh.magic, &pph, &pckt_count);
_my_printf("press [s] to break, any other keys to continue showing pcap packet content data.......\n");
chget = getchar();
if (chget == 's') {
break;
}
ppd = (u8 *)_my_buf_malloc((size_t)(pph.caplen));
fdpcap = read_pcap_packet_data(fdpcap, ppd, pph.caplen, &read_count);
if ( 0 != fdpcap) {
print_pcap_packet_data(ppd, pph.caplen);
fdpckt = write_pcap_packet_data(fdpckt, ppd, pph.caplen, &pckt_count);
free(ppd);
ppd = 0;
continue;
}
_my_buf_free(ppd);
ppd = 0;
}
break;
}
}
_my_pcap_close(fdpcap);
}
}
/*
* main - 测试main函数
*
*/
int main(int argc, char* argv[])
{
char pcap_pathname[255];
char packet_pathname[255];
pcap_test_demo(
"D:/09160016",
"D:/09160016.dat"
);
return 0;
}
#endif /* PCAP_CONSOLE_DEMO */
.