使用WinPcap和libpcap类库读写pcap文件(002)PCAP文件格式
本文基本翻译自https://wiki.wireshark.org/Development/LibpcapFileFormat,主要分析pcap文件的格式。
其中一些字段可能和现在的WinPcap类库里的字段不同,请结合当前WinPcap库分析。
libpcap文件格式
libpcap文件格式是TcpDump/WinDump,Wireshark/TShark,snort和许多其他网络工具中的主要抓包文件格式。
1 综述
这种文件格式是保存捕获网络数据的一个非常基础的格式。随着libpcap库成为了UN*X平台上“事实上的”网络捕获标准,它变成了开源世界里网络捕获文件的“普遍标准”(在商业网络捕获世界里似乎压根就没有像“普遍标准”这样的东西)。
Libpcap和libpcap的Windows接口“WinPcap”,使用同样的文件格式。
虽然有时候假设这种文件格式只适用于以太网(Ethernet),它可以用在许多不同的网络类型里面,在Wireshark支持的捕获媒体页面可以找到这样的例子;所有列出的类型都可以被libpcap文件格式处理。
基于libpcap的文件建议使用的文件扩展名是pcap。
Wireshark在wiretap库里处理所有捕获文件的I/O。你可以在wiretap/libpcap.c和.h文件里找到关于libpcap文件格式的更多细节。
2 文件格式
“在非官方的世界里”,存在有一些格式上的变化。下面将只说明在当前2.4版本里通用的格式。这个格式的版本已经很长时间没有改变过了(至少从1998年libpcap0.4开始),所以它的格式也不太可能发生改变,除了下面提到的PCAPng文件格式。
文件的一个官方变更版本是支持纳秒级精度时间戳的版本。当前libpcap和WinPcap的发行版不支持这种方式读取文件;只有在git trunk上的libpcap版本才支持这种读取。旧版本的Wireshark不能读取;当前版本的Wireshark可以读取并能显示完整的纳秒级分辨率时间戳。
文件有一个包含全局信息的全局头,后面跟着0个或多个捕获的包的记录,看起来就像这样:
Global Header | Packet Header | Packet Data | Packet Header | Packet Data | Packet Header | Packet Data | ... |
在捕获文件里的被捕获的包不需要像在网络上那样包含包中所有的数据;捕获文件可能只包含每个包的前N个字节。在这种捕获的形式里,这个N值叫做“snapshot length”或者捕获的“snaplen”。N可以是一个比包可能的最大长度还要大的值,这样可以确保捕获到的包没有被“切片”;在这种情况可以把这个值设为65535。
2.1 全局头
这个头是libpcap文件的开始,后面跟着第一个包头。
typedef struct pcap_hdr_s {guint32 magic_number; /* magic number */guint16 version_major; /* major version number */guint16 version_minor; /* minor version number */gint32 thiszone; /* GMT to local correction */guint32 sigfigs; /* accuracy of timestamps */guint32 snaplen; /* max length of captured packets, in octets */guint32 network; /* data link type */
} pcap_hdr_t;
magic_number:用来检测自身文件格式和字节序。写文件程序写入0xa1b2c3d4时,以本地的字节序格式写入这个字段。读文件程序可以读出0xa1b2c3d4(同样的字节序)或0xd4c3b2a1(相反的字节序)。如果读文件程序读出相反的0xd4c3b2a1值,它就知道后面的字段也需要反过来。对于纳秒级分辨率文件,写文件程序写入0xa1b23c4d,与原来不同两个低位字节内部交换高低4位,而读文件程序将会读出0xa1b23c4d(同样的字节序)或0x4d3cb2a1(相反的字节序)。
version_major, version_minor:文件格式的版本号(当前版本号是2.4)
thiszone:后面包头的时间戳的GMT(UTC)和本地时区之间的修正,以秒为单位。例如如果时间戳在GMT(UTC),thiszone就是0。如果时间戳在中欧时区(阿姆斯特丹,柏林,……),时间是GMT+1:00,thiszone必须是-3600。实际上,时间戳一直在GMT,所以thiszone一直是0。
sigfigs:理论上,时间戳在捕获中的精确度;实际上,所有的工具设置这一字段为0。
snaplen:捕获的“snapshot length”(典型值是65535或更多,但是可能被用户限制),参看下面的incl_len vs. orig_len。
network:链路层头类型,指定包开始的头的类型(例如1表示Ethernet以太网,参看tcpdump.org's link-layer header typespage后获取更多细节);这可以是各种各样的类型,例如802.11,带有多种无线电信息的802.11,PPP,令牌环网,光纤分布式数据接口等等。
注意:如果你需要一个用于libpcap文件的新的封装类型(network字段值),不要使用任何已经存在的值!也就是不要通过改变一个已经存在的条目来添加新的封装类型;避开已经存在的条目。另外,给tcpdump-workers@lists.tcpdump.org发邮件,申请一个新的链路层头类型值,并指定新值的用途。
2.2 Header记录(包)头
Each captured packet starts with (anybyte alignment possible):
每个捕获的包以下面的格式开始(所以字节尽可能对齐):
typedef struct pcaprec_hdr_s {guint32 ts_sec; /* timestamp seconds */guint32 ts_usec; /* timestamp microseconds */guint32 incl_len; /* number of octets of packet saved in file */guint32 orig_len; /* actual length of packet */
} pcaprec_hdr_t;
typedef struct pcaprec_hdr_s {
guint32ts_sec; /* timestamp seconds */
guint32ts_usec; /* timestamp microseconds*/
guint32incl_len; /* number of octets ofpacket saved in file */
guint32orig_len; /* actual length ofpacket */
} pcaprec_hdr_t;
ts_sec:包被捕获的日期和时间。这个值是距离1970年1月1日00:00:00GMT的秒数;这也被称作UN*X时间戳。你可以使用ANSI C标准中time.h里的time()函数来获取这个值,但是你也可以用更好的办法来获取这个时间戳的值。如果这个时间戳不是以GTM(UTC)为基准的,使用全局头中的thiszone字段来调整。
ts_usec:在常规的pcap文件中,这个字段表示包被捕获时的毫秒值,以ts_sec为基准偏移。在纳秒级分辨率文件中,这个值被捕获时的纳秒数取代,以ts_sec为基准偏移。要知道:这个值不能达到1秒(也就是1 000 000在常规的pcap文件;在纳秒级分辨率文件中这个值不能达到1 000 000 000);达到这个值时,必须增长ts_sec来避免这种情况。
incl_len:实际捕获的和保存在文件中的包数据的字节数。这个值不应该比orig_len或全局头的snaplen值大。
orig_len:包被捕获时,在网络中显示的包的长度。如果incl_len和orig_len不同,实际保存的包大小被snaplen限制。
2.3 包数据
实际的包数据,以incl_len个字节的数据团形式紧跟在包头后面,没有明确的字节队列。
3 库
应该很容易实现读写libpcap文件的函数,这实在是一种简单的文件格式。然而,如果你想用一个库来达到这个目的,或者如果你真的需要从一个实时的网络中捕获包,可以用下面这些库来做这些事:
libpcap:原始的这种文件格式(适用于基于UN*X的系统)
WinPcap:基于Windows的libpcap版本
还有适用于许多编程语言的封装可用(但是你必须已经安装了上面库中的一个):
Net::Pcap:基于Perl语言的libpcap封装
Jpcap:基于JAVA语言的libpcap封装
python-libpcap:基于Python语言的libpcap封装
Ruby/Pcap: 基于Ruby的libpcap封装
你可以给你最喜欢的编程语言添加一个libpcap封装,或者如果缺少这种封装就Google……
注意,如果你编写你自己的代码来读文件,在下面提到的“下一代libpcap”格式里读取任何捕获的文件都将失败。然而,如果你使用libpcap,当链接(在构建或运行时)到一个可以读取这些文件的libpcap/WinPcap的版本时,程序能够读取“下一代libpcap”文件,这些文件不使用当前libpcap API不支持的特性(比如来自多个接口带有不同的链路层数据类型的包),也不使用读取当前libpcap格式。由此观之,如果可能你应该使用libpcap/WinPcap,而不是自己编写代码来读这些文件。
4 缺陷
libpcap格式是非常简单的,这是它得到如此广泛应用的一个原因。不幸的是,它漏掉了一些有用的事情:
纳秒时间分辨率
用户评论:“从1432包开始显示连接故障”
接口信息(比如网卡制造商)
丢包计数(以及其他可能的计数)
…….
5 未来
libpcap文件格式达到了它的目的,这一点获得了广泛接受,但是这个格式缺少有用的特性。有一个下一代pcap文件格式的提议,可以在http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html获取到。新格式提供了许多在上面“缺陷”一节中提及的能力。
在现在和相当长的一段时间里,这仍然只是一个提议。Wireshark目前至少有能力读取一些pcap-NG文件,虽然它并不支持读取所有文件的能力,libpcap1.1.0和后续版本也只有有限的读取能力。NTAR - Network TraceArchival and Retrieval库仍在开发中。完成开发后,它能读写这种格式的记录,但是不能解释他们(像Wireshark那样解释);在将来,libpcap和Wireshark将使用这个库并解释里面的记录。
更多关于pcapng文件格式的细节参看WiresharkDevelopment/PcapNg。
6 讨论
更好的,将来可能使用单词“数据块”或“块”或其他词汇取代“包”。
相关文章:

图论-最短路径--3、SPFA算法O(kE)
SPFA算法O(kE) 主要思想是: 初始时将起点加入队列。每次从队列中取出一个元素,并对所有与它相邻的点进行修改,若某个相邻的点修改成功,则将其入队。直到队列为空时算法结束。 这个算法,简单的说就是队列优化的bellman-…

如何在HHDI中进行数据质量探查并获取数据剖析报告
通过执行多种数据剖析规则,对目标表(或一段SQL语句)进行数据质量探查,从而得到其数据质量情况。目前支持以下几种数据剖析类型,分别是:数字值分析、值匹配检查、字符值分析、日期值分析、布尔值分析、重复值…

html5网页怎么实现内容追加,纯js实现网页内容复制后自动追加自定义内容
网页操作内容复制内容后纯js实现监听自动追加自定义内容不少网站技术或者博客上有这样的处理,当我们复制代码的时候,会自动加上一段本信息版权为XXXX,这是怎么实现的呢?其实实现的方式很简单,可以在我的网站页面上绑定…

ios Standard Framework和Umbrella Framework
Standard Framework:标准库,通过引用对应的header文件而不是引用master header 文件来引用类(也可以通过引用Master Header file来引用需要使用的类),只需要暴露对应的header文件到Header文件夹下即可,不强制引用master header文件…
Win7使用Visual Studio 2010编译用于Qt4.8.6的MySQL驱动
其实编译过程在Qt Creator 的帮助文档里有,我就是照着做的,但是没成功,因为不能照搬照抄! 1.确保path环境变量里有QTDIR,这个就不细说了。 2.打开"开始"->"Microsoft Visual Studio 2010"->…

ios 常见性能优化
1. 用ARC管理内存 2. 在正确的地方使用reuseIdentifier 3. 尽可能使Views透明 4. 避免庞大的XIB 5. 不要block主线程 6. 在Image Views中调整图片大小 7. 选择正确的Collection 8. 打开gzip压缩 9. 重用和延迟加载Views 10. Cache, Cache, 还是Cache! 11. 权衡渲染方…

强化学习(七)时序差分离线控制算法Q-Learning
在强化学习(六)时序差分在线控制算法SARSA中我们讨论了时序差分的在线控制算法SARSA,而另一类时序差分的离线控制算法还没有讨论,因此本文我们关注于时序差分离线控制算法,主要是经典的Q-Learning算法。 Q-Learning这一…

react遇到的各种坑
标签里用到<label for>的,for 要写成htmlFor标签里的class要写成className组件首字母一定要大写单标签最后一定要闭合如果html里要空格转义, 注意不要漏了分号;style要写成style{{clear: both,backgroundColor:red,width:200px}}组件里能用<but…

html页面视频标签,html5基础标签(html5视频标签 html5新标签用法)
点评:html5基础,包括html5视频标签和html5新标签等标签用法,大家参考使用吧1、 声明的变化2、 指定字符编码的变化,html5中建议使用utf-83、 Html5中允许没有结束符,不算错误4、 不允许写结束标记的有:…

chronyd服务
一、makestep步进时间选项 最近做RHCE的实验,nfs用krb5p实现全程加密和身份认证,需要nfs服务端、客户端的时间与KDC的时间同步,否则kerberos分发的ticket就会失效,nfs不能挂载和访问。那么就需要在nfs的服务端、客户端都配置chro…

软件测试人员必备Linux命令(初、中、高级)
有些技能可以事半功倍,有些命运掌握在我们手中。熟练的掌握和使用这些命令可以提高工作效率,并且结合这些命令对测试过程中遇到的问题进行一些初步的定位。 1 目录与文件操作 1.1 ls(初级) 使用权限:所有人 功能 : 显示指定工作目录下之内容&…

酷派android手机怎么截屏,酷派S688怎么截屏截图?
夏普AQUOS S2事水滴全面屏,搭配骁龙630处理器,个人手里就是这货,目前售价千元内,按需求不高的人,可以考虑,不过系统不很行基于Android 7.1.1深度优化的Smile UX系统实在表现一般。~~~~根据美国FCC的认证信息…

01 多线程概念及其实现方式
多线程是编程过程里必不可少的内容,学习多线程,就先要了解进程和线程的概念。进程:是指当前正在运行的程序,是一个程序在内存里的执行区域;线程:是在进程里的一个执行控制单元,执行路径…

负载均衡层次分析
什么是负载均衡 负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一,它通常是指,将请求/数据【均匀】分摊到多个操作单元上执行,负载均衡的关键在于【均匀】。 常见的负载均衡方案 常见互联网分布式架构如上,分为客…

Python基础01-Python环境搭建与HelloWorld
目录 从今天开始学习Python Python环境搭建 安装gcc Python源码包安装 开始Python第一个代码HelloWorld! 从今天开始学习Python 为啥选择Python,可能是跟随潮流吧。我现在不知道为什么学习Python,但是可能一年到一年半以后,…

oracle与mysql创建表时的区别
oracle创建表时,不支持在建表时同时增加字段注释。故采用以下方式: #创建表 CREATE TABLE predict_data as (id integer NOT NULL, uid varchar2(80),mid varchar2(80),time date ,conten…

在Linux上安装Memcached服务
下载并安装Memcache服务器端 服务器端主要是安装memcache服务器端. 下载:http://www.danga.com/memcached/dist/memcached-1.2.2.tar.gz 另外,Memcache用到了libevent这个库用于Socket的处理,所以还需要安装libevent,libevent的最…

图形化编程 html,用GoJS实现图形化交互编程界面示例
JavaScript语言:JaveScriptBabelCoffeeScript确定function init() {var $ go.GraphObject.make; //for conciseness in defining node templatesmyDiagram $(go.Diagram, "myDiagramDiv", //Diagram refers to its DIV HTML element by id{"undoMan…

枚举位移计算操作
如: typedef NS_ENUM(NSInteger, Test) { // 十进制 二进制 TestA 1 << 0, // 1 00001 TestB 1 << 1, // 2 …

Python基础02-Python基础
脚本的第一行 Python脚本的第一行,写Python解释器的路径。这样就可以直接执行Python脚本。 脚本编码 Python2需要指定脚本的编码,Python3不需要指定。 # -*- coding:utf8 -*- 使用input做简单的交互 username input(请输入用户名密码:) password …

SpringBoot上传文件大小限制
SpringBoot默认上传文件大小不能超过1MB,超过之后会报以下异常: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.at org.apache.tomcat.…

html实时显示log,websocketd 实现浏览器查看服务器实时日志
操作系统CentOS7下载 websocketd安装 nc 命令yum install nmap-ncat创建监听脚本cat > cmd.sh <#!/bin/bashpkill -x ncwhile :; donc -nkl 10088sleep 1done创建 log.htmlbody{background-color: #0e1012;color: #ffffff;}*{margin: 0; padding: 0;}#msg{overflow:auto;…

git 合并两个分支的某个文件
软件开发基本都是多个feature分支并行开发,而在上线前有可能某个分支的开发或测试还没有完成,又或者是产品调整,取消了该分支功能的上线计划,我们在release前不合并该分支即可,然而如果该分支中的某些小调整却需要上线…

lattice diamond 3.7安装破解
第一步安装:执行.EXE文件,一直下一步,最后license选择没有USB什么的那个(具体记不清了)。 第二步破解:安装完成后在环境变量中将license路径指定到license文件即可(LM_LICENSE_FILE d:\lscc…

Python基础03-运算符
运算符 算数运算符 算数运算符符号运算数字用法举例字符串用法举例加a 2 3 print(a) # 5s1 "hello" s2 "world" s s1 s2 print(s) # helloworld-减a 12 - 3 print(a) # 9*乘a 12 * 3 print(a) # 36s1 "hello" s2 "world" s…

shell下的作业管理(转)
作业管理 举例来说,我们在登陆 bash 后, 想要一边复制文件、一边进行数据搜寻、一边进行编译,还可以一边进行 vi 程序撰写! 当然我们可以重复登陆那六个文字介面的终端机环境中,不过,能不能在一个 bash 内达…

合并模拟器和真机的静态库动态库aggregate
创建Aggregate的target 在Build Phases 添加Run Script,内容为 scriptFile${SRCROOT}/universalA.shsh ${scriptFile} universalA.sh放在工程根目录,内容为: if [ "${ACTION}" "build" ]then echo "合并模拟器真机库" ta…

html表格联动,html前端基础:table和select操作
html前端基础:table和select操作发布时间:2020-05-13 09:58:10来源:亿速云阅读:196作者:Leah这篇文章主要为大家详细介绍html前端基础中有关table和select的操作,配合代码阅读理解效果更佳,非常…

Python基础04-数据类型:数字、布尔、字符串
目录 数字 布尔 字符串 字符串的常用函数 字符串的内存分析 字符串练习题 数字 判断是数字类型还是字符串类型。 # <class str> 123 a "123" print(type(a), a)# <class int> 123 b int(a) print(type(b), b) 十进制、二进制、八进制、十六进…

一起学Hadoop——实现两张表之间的连接操作
---恢复内容开始--- 之前我们都是学习使用MapReduce处理一张表的数据(一个文件可视为一张表,hive和关系型数据库Mysql、Oracle等都是将数据存储在文件中)。但是我们经常会遇到处理多张表的场景,不同的数据存储在不同的文件中&…