Fine Packet Builder 快速入门
Fine Packet Builder
快速入门
Version 2.0 beta2
2009 年 8 月 29 日
Copyright
© www.fineqt.com
http://code.google.com/p/fpb/
頁 1/65
Fine Packet Builder 快速入门
变更履历
版数 项目 章-节-项 变更内容 日期
2.0 1 ALL 简体中文版首版 2009/8/2
1 1 2.0
2 3
1 3,4,5,6 新增内容 2.0
2 1,7 第 1 章说明部分有修改,原第 3 章改为第 7 章。
2.0 1 2 新增“例子程序的执行”。 2009/8/29
Beta2 版发布,增加了 HTTP 协议的例子。 2009/8/17
2009/8/27
http://code.google.com/p/fpb/
頁 2/65
Fine Packet Builder 快速入门
目录
1. 概要 ............................................................................................................................................... 5
2. 安装 ............................................................................................................................................... 7
3. 系统构成 ....................................................................................................................................... 9
4. 一个完整的协议定义与 API使用例 ................................................................................................11
4.1. Ethernet协议的定义 .............................................................................................................11
4.2. ARP协议模拟 ....................................................................................................................... 14
5. 协议语法表示语言 ....................................................................................................................... 22
5.1. TTCN-3 语言简介 ................................................................................................................ 22
5.2. PSN的语言元素概要 ............................................................................................................ 23
5.3. 模块 ..................................................................................................................................... 23
5.4. 注释 ..................................................................................................................................... 24
5.5. 类型和值 .............................................................................................................................. 25
5.5.1. 概要 .............................................................................................................................. 25
5.5.2. 基本类型和值 ................................................................................................................ 25
5.5.3. 基本类型的子类型 ......................................................................................................... 27
5.5.4. 结构化的类型和值 ......................................................................................................... 28
5.5.5. 类型兼容性 .................................................................................................................... 33
5.6. 引入 ..................................................................................................................................... 33
5.7. 常量 ..................................................................................................................................... 34
5.8. 模块参数 .............................................................................................................................. 35
5.9. 枚举标签集合 ....................................................................................................................... 35
5.10. 模板 .................................................................................................................................. 36
5.11. 描述属性 ........................................................................................................................... 36
5.11.1. 概要 ........................................................................................................................... 36
5.11.2. 编码和编码变量描述属性 ........................................................................................... 37
5.11.3. 字段的引用 ................................................................................................................ 40
5.11.4. 枚举标签集合和枚举标签集合引用描述属性 .............................................................. 42
5.11.5. 运行时设置描述属性 .................................................................................................. 42
6. 用户 API ...................................................................................................................................... 43
6.1. 概要 ..................................................................................................................................... 43
6.2. com.fineqt.fpb.lib.api.module包 ......................................................................................... 43
6.3. com.fineqt.fpb.lib.api.value包 ............................................................................................ 44
6.4. com.fineqt.fpb.lib.api.util包 ............................................................................................... 45
6.5. com.fineqt.fpb.lib.api.util.buffer包 .................................................................................... 45
6.6. com.fineqt.fpb.lib.api.comm.pcap包 ................................................................................... 46
7. API和协议定义模块使用例 .......................................................................................................... 48
7.1. ARP协议使用例 ................................................................................................................... 48
http://code.google.com/p/fpb/
頁 3/65
Fine Packet Builder 快速入门
7.2. Ping应用 .............................................................................................................................. 48
7.3. Traceroute应用 .................................................................................................................... 53
7.4. TCP协议连接的模拟 ............................................................................................................ 56
7.5. 模拟 HTTP的 GET命令 ......................................................................................................... 62
http://code.google.com/p/fpb/
頁 4/65
Fine Packet Builder 快速入门
1. 概要
Fine Packet Builder(简称FPB)是开源免费数据包生成与协议分析工具,同时还提供了著名的PCAP
数据包截取软件包的Java 封装。FPB 使用独创的协议语法表示语言(Protocol Syntax Notation )来定义
协议的格式与编码和解码规则,可以在基本不编程(或很少编程,如checksum计算)的情况下定义自己
的协议。协议语法表示语言是建立在TTCN-3
分的语法,并且根据协议分析功能的需要进行了扩展。另外通过FPB 的通用Java API 可以对面向协议栈的
数据包进行创建、编辑、编码、解码、完整性验证和链路层发送和接收等操作。
由于 FPB 具有,用协议语法表示语言描述的协议语法直观易懂;Java API 的功能强大且简洁易用;内
置协议众多且使用实例丰富;等优点,所以可以将其广泛地应用于流量生成、协议分析、协议模拟、协议
学习和协议测试等方面。
• 已经实现(v2.0.beta2 版)的功能列表:
① 通用 CD (编码与解码器)框架。使用协议语法表示语言来描述,并且具有各种自动化功能,其
特点如下:
A) 同时支持面向数据包(如 ICMP)和面向流(如 HTTP)两种类型的协议,并且可以使用统
2
语言的基础上的,它继承了 TTCN-3 语言的协议定义相关部
1
一的描述规则。
B) 提供编码规则描述属性集,使得编码和解码器的绝大多数功能可以仅通过书写描述属性就能
够实现。
C) 字段的自动计算功能,通过描述属性定义的长度字段和对齐字段可以自动计算自己应有的值。
D) 数据包内容打印功能,可以以树形结构的文本形式打印数据包的内容和各个字段值的描述。
② 数据包内容完整性的验证。使用协议语法表示语言的类型限制条件规则(与 TTCN-3 语言的规则
相同)来描述数据的完整性规则,可以通过 Java API 根据该完整性规则来自动验证数据包内数据的
完整性。
③ PCAP 软件包的封装。用 Java 封装了 PCAP 软件包,支持所有 PCAP 原有的功能。为方便用户
的使用,对 Pcap 原有基于函数的 API 进行了整理和归纳,提供了简洁明了的基于 Java 接口的 API 。
④ 已提供的协议 CD 实现:
Ethernet, ARP, ICMPv4, IPv4, ICMPv6, IPv6, UDP, TCP, HTTP
⑤ 提供了多个应用例子,包括用 ARP 协议来取得 MAC 地址,用 ICMP 协议来实现 Ping 和
Traceroute 应用,以及 TCP 的连接开始和终了示例等。
• 正在开发的功能列表:
① 符合 TTCN-3 语言规范的模版功能。
② 协议 CD 实现:SIP, PPPoE, LT2Pv2, L2TPv3 等。
1
Pcap是开源的数据包截取软件包,它在Windows上的实现是WinPcap。具体内容可以参考
www.winpcap.org 和 www.tcpdump.org。
2
TTCN-3 是ETSI制定的通用协议测试语言标准,具体内容可以参考http://www.ttcn-3.org/ 和
http://www.ttcntest.com/。
http://code.google.com/p/fpb/
頁 5/65
Fine Packet Builder 快速入门
本工具希望提供一个灵活、使用简便而且功能强大的 CD 框架,从而可以快速开发各种类型的 CD ,并
且用它实现尽可能多协议的 CD 供大家使用,也欢迎大家用它实现自己的协议并共享给别人使用。
以下是相关网站的链接:
FPB开源项目网站
WinPcap官方网站
Pcap官方网站 www.tcpdump.org
TTCN-3 官方网站 http://www.ttcn-3.org/
TTCN-3 中国社区网站 http://www.ttcntest.com/
http://code.google.com/p/fpb/
www.winpcap.org
http://code.google.com/p/fpb/
頁 6/65
Fine Packet Builder 快速入门
2. 安装
Fine Packet Builder 的安装文件分为执行库和源程序两种形式,它们都是 ZIP 压缩文件形式,解压缩
后就可以直接使用了。执行库文件里包括 FPB 执行所需要的环境,比如 Java 库文件等,文件名称里包
括了版本信息和发布的时间,比如 fpb_2.0.beta1.v200907311552.zip 。源程序文件里是 FPB 库本身的
开发和调试所需的源程序和 Eclipse 工程目录。
(1) 执行库安装文件的安装和目录结构
执行库安装文件解压缩后就可以直接使用,其文件目录如下:
+ fpb_2.0.beta1 安装根目录
|- doc JavaDoc 形式的 Java API 说明
|- lib 执行所需的第三方库文件
|- antlr-runtime-3.1.3.jar
|- …
|-protocol 协议定义模块
|- ArpProtocol.module
|- …
|- sample FPB 使用例子的 Java 源程序。
|- finepbuilder_2.0.beta1.v200907311514.jar FPB 的 Java 类库文件
|- fpblib.dll FPB 的本地动态库文件
|- fpbprotocols_2.0.beta1.v200907311528.jar protocol 目录内协议定义模块所使用的功能扩充
类库。
(2) 源程序安装文件的安装和目录结构
解压缩源程序安装文件后将内部的 Eclipse 工程文件导入到 Eclipse 开发环境后就可以使用了,文件名
则类似于 fpb_2.0.beta1_src.v200907311559.zip 。另外由于 com.fineqt.fpb.lib 项目里使用了目录链接,
所以需要在在 Eclipse 的 Preferences->General->Workspace->Linked Resource 下加入如下变量
FPB_LIB_MODEL_PROJECT :D:\work\fpbdistworkspace\com.fineqt.fpb.lib.model
解压缩后的目录结构如下:
+
|- com.fineqt.fpb.lib 主工程目录
|- com.fineqt.fpb.lib.model 模型工程目录
|- com.fineqt.fpb.protocol 协议模块扩展功能工程目录
(3) FPB 执行环境的安装和设置
因为本工具是以 Java 语言来开发的,所以需要事先安装 Java Runtime 。链路层通信和数据包截取文
件相关联的功能使用了 WinPcap 库,所以 WinPcap 的安装也是需要的。下面是安装方法的说明。
① Java Runtime 的安装
JRE(Java Runtime Enviroment)(1.6 以上)的安装文件和安装说明可从以下链接下载。
http://java.sun.com/javase/ja/6/download.html
② WinPcap 的安装
WinPcap( 3.1 以上)的下载链接和安装说明在以下的场所。
http://www.winpcap.org/install/default.htm
③ FPB 运行库的安装
FPB 运行库文件可从如下场所下载,下载后直接解压缩即可。
http://code.google.com/p/fpb/
頁 7/65
Fine Packet Builder 快速入门
http://code.google.com/p/fpb/downloads/list
④ 环境参数的设置
在执行时 FPB 需要知道安装目录的位置从而载入本地动态库(.dll 文件)和默认协议定义模块文件,所
以如果没有在程序中强制指定的话,就要设置 FPB_HOME 环境变量来告知 FPB 运行库。Windows
下的执行命令如下:
set FPB_HOME=D:\tools\fpb_2.0.beta1
(4) 例子程序的执行
在运行库安装目录下 sample 目录里有多个 FPB API 和协议模块的使用例源程序,清单如下:
+ sample\com\fineqt\fpb\protocol\sample
|- ArpApp.java 通过 Arp 协议来取得设置为特定 IP 地址的机器的 MAC(物理)地址。
|- PingApp.java 使用 ICMPv4 协议的 Echo Request 和 Echo Reply 报文来实现 Ping 应用。
|- TracerouteApp.java 使用 ICMPv4 协议的 Echo Request 和 Echo Reply 报文和 IPv4 协议的 TTL
字段来实现 Traceroute 应用。
|- TcpConnectionSample.java 模拟 TCP 协议连接的三向握手开始和终了。
|- SampleMain.java 用于执行各个例子程序的主程序类。
|- HttpGetSample.java 使用 HTTP 协议的 GET 命令来取得网站的资源。
执行例子程序前先要按照“
2(3) ”的说明准备好运行环境,接着通过Eclipse3等 Java 开发工具建立 Java
项目,然后在项目中引入安装目录下”lib” 目录下的所有第三方库和finepbuilder_*.jar 和fpbprotocols_*.jar
两个主库文件后就可以执行例子程序的主程序com.fineqt.fpb.protocol.sample. SampleMain 类了。另外
由于例子中使用了本地IP 地址和物理地址(MAC 地址)等参数,在执行前需要修改一下SampleMain.java
文件中的相关设置,SampleMain.java 文件的说明具体可以参考“
参考“
7”。
4.2(2)(a)”,各个例子的说明可以具体
如果希望不通过 Eclipse等开发工具就直接执行例子程序则可以使用安装目录下的“ runsample.xml”
4
ANT
批处理文件,该文件首先将所有的例子程序用 javac 编译后,然后直接用 java命令来执行
com.fineqt.fpb.protocol.sample. SampleMain类。 Windows下的执行命令如下,并且执行时当前目录必
须是 FPB的安装目录。
ant -v -f runsample.xml
另外,由于使用了 javac 命令,所以 J AVA_HO M E 环境变量需要指向 JDK(不是 JRE )的安装目录,并
且 ant 命令也需要在 OS 的检索路径(PATH 环境变量)中可见。还有 SampleMain.java 使用的是 UTF8
编码,编辑时需要使用支持 UTF8 的编辑器(比如 Eclipse )。
3
Eclipse是最为流行的用于开发Java的IDE,可见http://www.eclipse.org/。
4
ANT是Java环境下最为流行的编译和批处理工具,可见http://ant.apache.org/。
http://code.google.com/p/fpb/
頁 8/65
Fine Packet Builder 快速入门
3. 系统构成
FPB主要由三部分构成,分别为协议模块模型类库、运行库和内置协议定义。协议模块模型类库是为了
描述协议语法表示语言(Protocol Syntax Notation, 简称PSN )的结构而用EMF
协议的模块文件的内存模型就使用该模型类库来构建。运行库是FPB 的主体,它包括文件编译器、通用CD
架构和Pcap 通信等功能模块。内置协议定义由根据PSN 所描述的协议模块文件和协议编码扩展类库两部分
构成。
5
定义的模型类库,定义
协议编码
FPB 运行库
扩展类库
协议模块
文件
...
协议模块
文件
值对象
编译模块
文件并登
记
Value Primitive
Container
Module
Parser
Module
Registry
Value
Factory
List
编译并创
建
创建并用模型
对象初始化
调用类型功能
创建
Integer
Float
...
Record
...
RecordOf
SetOf
已接收/待
发送数据
模块模型对
象
模块描述对
象
待编码/ 已解码
值对象
值对象
模块描述对象
ModuleExt
TypeExt ConstantExt
模块模型对象
Module
Type Constant
Byte数组
调用类型功能
包含
包含
Pcap
Socket
已编码/待
解码数据
Value
Serializer
Value
Dumper
...
...
接收/ 发送
数据
已接收数据
Ensurable
BitBuffer
增量解码
数据
打印值对象
描述
范例
说明
继承
数据传输或生成
网络实
体
标准输
出
図 3- 1FPB 系统构成图
図 3- 1描述了FPB 的系统构成概况。系统的三大构成部分中,模块模型由“模块模型对象”来表示,运
行库由“FPB 运行库”来表示,内置协议定义由“模块文件”和“协议编码扩展类库”来表示。图中“模
块描述对象”内的元素与“模块模型对象”内的元素一一对应,模型对象只具有模块内元素的数据模型,
而编码和解码等具体功能则包含在描述对象内,所以解码、编码、数据完整性验证以及值对象的创建和文
本描述的取得等功能最终都要通过“模块描述对象”来完成。图中“值对象”与模块文件中所能描述的值
类型的种类相匹配,用来存储协议中字段的具体值。
FPB 中的协议定义以协议模块为单位来管理,在系统启动时并不将所有的协议模块载入,只是将所有搜
索路径上的合法(.module 为扩展名)协议模块文件以Proxy 形式在Module Registry 中登记一下,在实际
http://code.google.com/p/fpb/
頁 9/65
Fine Packet Builder 快速入门
使用时才将完整内容载入内存,这就是所谓的“延迟载入技术”。比如在创建协议模块文件中所描述类型
的值对象时,首先通过Module Registry 来取得Valu e Fact ory ,Value Factory与协议模块文件是一一对
应的,当该协议模块还没有载入时Module Registry 则会调用Module Parser( 通过ANTLR
译外部的协议模块文件,然后从得到的ModuleExt( 模块描述对象)哪里取得Value Factory;接着用Valu e
Factory来创建值对象。另外,编码和解码操作通过 Value Serializer来完成,值对象的文本描述打印通过
Value Dumper来完成,链路层的通信则通过Pcap Socket来完成。还需特别指出,针对HTTP协议等基于
流协议的解码 FPB提供了增量解码的功能,也就是将非连续的数据存入 Ensurable Bit Buffer中, Val ue
6
编译类库 )来编
Serializer则通过该 Buffer对象来取得数据并用阻塞方式完成面向流的解码。
5
EMF是 Eclipse Model Framework的缩写,用来定义通用软件模型的架构。
6
ANTLR是 Another Tool for Language Recognition的缩写,是开发编译器的辅助工具。
http://code.google.com/p/fpb/
頁 10/65
Fine Packet Builder 快速入门
4. 一个完整的协议定义与 API 使用例
本章以 Ethernet 协议为例说明协议模块文件的结构和书写规则,用 ARP 协议为例说明 FPB 的 Java
API 的使用方法,力求通过本章使读者对 FPB 的使用方法有一个整体的了解。
4.1. Ethernet 协议的定义
所谓协议就是控制网络中不同实体(比如计算机和路由器)间数据通信的规则。协议定义要传送什么,
怎样进行通信,以及何时进行通信。协议格式就是协议互相传送数据的结构或格式,而数据包或帧等(后
统称为数据包)是通信中传送数据的单位,通常由一个或多个协议所构成。要用协议来进行通信的话,那
就离不开根据各协议格式来生成数据包、解析数据包了。FPB 使用独有的协议语法表示语言(PSN )来
描述协议的格式以及数据包的编码、解码、数据完整性验证和描述文本表示等规则。下面以 Ethernet(以
太网)协议为例进行详细的说明。
首先我们看一下 Ethernet 协议的格式。
0 16
上图各字段的内容:
• 目的地址 6 字节字段。下一节点的物理地址( MAC 地址)。
• 源地址 6 字节字段。前一节点的物理地址( MAC 地址)。
• 类型 2 字节字段。上层协议的类型。比如 IP 是 0x0800, ARP 是 0x0806。
• 数据 数据部分。最小长度 46 字节,最大长度 1500 字节。
• FCS 4 字节字段。差错检测信息,使用的是 CRC-32 算法。
8
目的地址
类型
24
目的地址
源地址
源地址
数据和填充
(可变长度 )
FCS
図 4-1 Ethernet 协议格式
32 位
接下来看一下 Ethernet 协议的协议模块文件。
module EtherProtocol {
import from BasicTypeAndValues {
type Oct6, UInt16, Oct4, MacAddress
}
import from Ipv4Protocol {
type Ipv4Protocol
}
import from ArpProtocol {
type ArpProtocol
}
import from GlobalEnumSets {
enumset EtherTypes
http://code.google.com/p/fpb/
①
②
頁11/65
Fine Packet Builder 快速入门
}
import from Ipv6Protocol {
type Ipv6Protocol
}
type record EtherProtocol {
MacAddress dstAddress,
MacAddress srcAddress,
UInt16 etherType,
EtherPayload payload,
Oct4 fcs optional
} with {
variant Protocol(true); PushEmptyField([DECODE], "etherType")
variant(etherType) SetField([DECODE])
enumref(etherType) EtherTypes
}
type union EtherPayload {
Ipv4Protocol ipv4,
ArpProtocol arp,
Ipv6Protocol ipv6,
octetstring data
} with {
variant CaseRef("-etherType", #UInt16); CaseDefault(data)
variant(ipv4) CaseCond(UInt16 (0x0800))
variant(arp) CaseCond(UInt16 (0x0806))
variant(ipv6) CaseCond(UInt16 (0x86DD))
}
} with {
encode "FPB"
variant ByteOrder(BIG_ENDIAN)
}
表 4.1-1 描述 Ethernet 协议的协议模块文件
④
③
⑤
⑥
⑦
⑧
① 协议模块的定义。用 module 语句来定义模块名称为 EtherProtocol 的模块,协议模块里可以定
义类型、模板、常量、模块参数和枚举标签集合等元素。模块是顶级元素,一个文件内只能有一个模
块,其他元素都需要在模块内部定义。
② 引入别的模块的元素。用 import 语句引入了 BasicTypeAndValues 协议模块里所定义的 Oct6、
UInt16、 Oct4、 MacAddress 四种值类型。为了使用别的模块里定义的值类型等元素,必须事先用
import 语句引入它们。可以使用原模块内的名称来引用引入类型等引入元素,当引入元素之间或与本
模块元素之间的名称发生冲突时,可以使用被引入模块名加上“.”的前缀来区分它们。
③ 记录(record )类型定义。用 type 语句来定义名称为 EtherProtocol 的记录类型。记录类型是容
器类型的一种,它可以包含复数个字段,各个字段在协议格式中是顺序排列的关系。
④ 字段定义。定义类型为 MacAddress ,名称为 dstAddress 的字段。该字段的附加属性可以通过
尾部的 with 语句来定义。
⑤ EtherProtocol 类型的描述属性的定义。使用 with 语句来定义类型和字段的描述属性。描述属性
是对于类型或字段的扩展描述,在 FPB 中可以有 encode(编码)、variant(编码变量)、enum(枚举标
签集合)、enumref(枚举标签集合引用)和 runtime(运行时设置)五种类型。“variant”等关键字之
http://code.google.com/p/fpb/
頁 12/65
Fine Packet Builder 快速入门
后没有括号表示该描述属性针对整个类型,有括号则针对括号内指定的字段。“ variant
Protocol(true); PushEmptyField([DECODE], "etherType")”语句表示 EtherProtocol 类型是协议
的根类型,并且在解码(decode )时在堆栈中设置一个名为“etherType ”的堆栈字段。
“variant(etherType) SetField([DECODE])”语句表示在解码“etherType ”字段后,将该字段的值
设置到同名的堆栈字段中,即前面 PushEmptyField 设置的堆栈字段。“enumref(etherType)
EtherTypes ”语句表示引用名为“EtherTypes”的枚举标签集合来解释“etherType”字段的文本描
述,该文本描述将用于数据包的文本内容打印(通过 Value Dumper)。
⑥ 联合(union) 类型的定义。用 type 语句来定义名称为 EtherPayload 的联合类型。联合类型与记
录类型一样都是容器类型的一种,它可以定义被包含的字段,不过与记录类型不同的是联合类型同时
只能有一个字段有效。
⑦ EtherPayload 类型的描述属性的定义。“variant CaseRef("-etherType", #UInt16);
CaseDefault(data) ”语句声明在解码时,EtherPayload 类型将引用“etherType ”堆栈字段的值来
判断那个子字段有效,当没有找到有效的子字段时将以“data ”字段为默认有效字段。“variant(ipv4)
CaseCond(UInt16 (0x0800)) ”语句声明在解码时,如果 CaseRef 指定的引用字段( ”etherType” 堆
栈字段)值是 UInt16 类型的 0x0800 ,则“ipv4 ”字段为有效子字段。
⑧ EtherProtocol 模块级别描述属性的定义。“encode "FPB" ”语句表示该模块内的默认编码类型为
“FPB ”。“ variant ByteOrder(BIG_ENDIAN) ”语句表示该模块内部类型的默认字节顺序
7
将是
BIG_ENDIAN 类型。
上述协议模块文件内的的每个字段是和协议格式相对应的,下面给出它的对应关系。
类型 类型字段 字段类型 对应协议格式字段
EtherProtocol
dstAddress MacAddress
srcAddress MacAddress
etherType UInt6
payload EtherPayload
目的地址,MAC 地址。
源地址,MAC 地址。
类型,无符号 16 位整数。
数据
fcs Oct4 FCS
EtherPayload
ipv4 Ipv4Protocol
arp ArpProtocol
ipv6 Ipv6Protocol
data octetstring
上位协议是 Ipv4 时有效
上位协议是 Arp 时有效
上位协议是 Ipv6 时有效
其他情况下有效
表 4.1-2 协议模块内字段和协议格式字段的对应关系
7
字节顺序表示编码和解码时按什么顺序来解释多字节的整数或者浮点数。比如说 BIG_ENDIAN情况下
对于四个字节的无符号整数 0x04030201,将按照从高到低的字节顺序来解释,即 0x04 -> 0x03 -> 0x02 ->
0x01。如果是 LITTLE_ENDIAN,前述情况将按 0x01 -> 0x02 -> 0x03 -> 0x4 顺序来解释。
http://code.google.com/p/fpb/
頁 13/65
Fine Packet Builder 快速入门
4.2. ARP 协议模拟
以太网(局域网)内两台计算机或设备互相通信的时候,需要知道对方的MAC 地址(物理地址)才能将
数据通过以太网协议传送给对方。但往往通信的时候只知道对方的IP 地址(逻辑地址) ,那我们是怎样
和对方打交道的呢?这就是ARP 的功劳了,ARP的工作就是通过IP地址来查询MAC地址。那么看一下ARP
是怎么工作的(
図 4- 2)。
查找 IP 地址为 192.168.1.1 的节
理地址
请求
)ARP 请求用广播发送
物理地址是 00:16:cf:2d:ce:e4
回答
B)ARP 回答用单播发送
図 4- 2ARP 的工作原理
ARP 发送广播请求数据包,向同一网上所有设备询问特定 IP 地址相对应的 MAC 地址。其它设备接到
ARP 请求数据包后,先看一下请求的 IP 地址是不是自己,不是的话就丢弃它,是的话就将自己的 MAC
地址填入 ARP 回答数据包,并将其用单播数据包发回请求方。这样,请求方就知道了通信对方的 MAC
地址了。
(1) 协议格式
那么,ARP 数据包里都放些什么信息呢?那就来看一下ARP 协议的协议格式(
ARP 数据包具有以下的一些字段:
• 硬件类型 这是 16 位字段,用来定义运行 ARP 的网络的类型。每一个局域网基于其类型被指派
给一个整数。例如,以太网是类型 1 。ARP 可用在任何网络上。
• 协议类型 这是 16 位字段,用来定义协议的类型。例如,对于 IPv4 协议,该字段的值是 0x0800
ARP可用于任何高层协议。
• 硬件长度 这是 8 位字段,用来定义以字节为单位的物理地址长度。例如,对以太网是 6 。
• 协议长度 这是 8 位字段,用来定义以字节为单位的逻辑地址长度。例如,IPv4 是 4 。
• 操作 这是 16 位字段,用来定义数据包的类型。已定义了两种类型:ARP 请求(1 ),ARP 回答
(2 )。
• 发送端硬件地址 这是可变长度字段。用来填写发送端物理地址。长度由“硬件长度”字段决定。
図 4- 3)。
8
。
http://code.google.com/p/fpb/
頁 14/65
Fine Packet Builder 快速入门
• 发送端协议地址 这是可变长度字段。用来填写发送端逻辑地址。长度由“协议长度”字段决定。
• 目标硬件地址 这是可变长度字段。用来填写目标物理地址。长度由“硬件长度”字段决定。
• 目标协议地址 这是可变长度字段。用来填写目标端逻辑地址。长度由“协议长度”字段决定。
0 16
8
硬件类型
硬件长度
协议长度 操作
发送站硬件地址
(例如:以太网是 6 字节
发送站协议地址
(例如:IP 是 4 字节)
目标硬件地址
(例如:以太网是 6 字节,发送请求时不填入
目标协议地址
(例如:IP 是 4 字节)
図 4- 3ARP 协议的协议格式
24
协议类型
请求 1 ,回答 2
)
)
32 位
ARP 协议的协议模块文件是“ ArpProtocol.module”,该文件在 FPB 的安装目录里可以找到。下面给
出协议模块文件内类型和字段的说明,以及与协议格式原来字段的对应关系。
类型 类型字段 字段类型 对应协议格式字段
ArpProtocol
(2) 协议客户端模拟实现
接着来说明如何用 Java API 来实现 ARP 客户端的模拟。也就是,向客户端所在的局域网所有的设备询
问特定 IP 地址对应的 MAC 地址。具体来说,先将请求的 IP 地址填入 ARP 请求数据包并将其用广播形
式发送,然后接收以单播形式发回来的 ARP 回答数据包并从中取出对方的 MAC 地址,如果等待一定时
间回答数据包仍然没有到达的话就认为超时。
在 FPB 安装目录下 sample 目录里有多个 FPB API 和协议模块的使用例源程序,其中 ARP 客户端模
hwType UInt16
protocolType UInt16
hlen UInt8
plen UInt8
operation UInt16
senderHwAddress octetstring
senderProtocolAddress octetstring
targetHwAddress octetstring
targetProtocolAddress octetstring
硬件类型。
协议类型,0x0800 为 IPv4,0x86DD 为
IPv6
硬件长度。
协议长度。
操作。
发送端硬件地址
发送端协议地址
目标硬件地址
目标协议地址
拟的主体程序是 com.fineqt.fpb.protocol.sample.ArpAp 类,ArpApp 类的使用则在相同包的 SampleMain
类里。SampleMain 类内包含有主函数 mian() ,所以实验时只要直接执行该类就可以了。
(a) SampleMain 类及 ArpApp 类使用例的源程序及说明
8
0x作为前缀的数字是以 16 进制来表示。
http://code.google.com/p/fpb/
頁 15/65
Fine Packet Builder 快速入门
public class SampleMain { 1
//本地的物理地址
2
private static final String
3
//本地的 IP 地址
4
5
private static final String
//FPB 的安装根目录
6
private static final String
7
//FPB 协议定义文件所在的目录,通常是 FPB 的安装根目录下的 protocol 目录。
8
private static final String
9
"D:/work/ttcnworkspace/com.fineqt.fpb.protocol/protocol" ;
10
//网络接口数组
11
private static NetworkInterface[]
12
//默认使用网络接口序号
13
final static int
14
15
public static void main(String[] args) throws Exception {
16
//FPB 系统初始化
17
IFpbSystem.
18
SampleMain main = new SampleMain(); 19
20
//Arp
main.testArp();
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
...
}
public void testArp() throws Exception {
String dstIp = "192.168.11.1";
//生成 Pcap 套接字来实现链路层通信
IPcapSocket socket = IPcapSocketFactory.
socket.setDevice(
//生成 Arp 对象
ArpApp arp = new ArpApp(socket,
//设置是否打印数据通信内容
arp.setDumpPacket(true );
//取得目标设备的 MAC 地址
String dstMac = arp.askMac(dstIp);
//打印
System.
}
...
public static NetworkInterface getInterface() throws SocketException {
if (
}
return
}
}
INTERFACE_INDEX
out
.println("Mac for " + dstIp + " is " + dstMac + "." );
ifs
== null ) {
ifs
= IPcapSocketFactory.
ifs[INTERFACE_INDEX
LOCAL_MAC
LOCAL_IP
FPB_HOME
FPB_PROTOCOL_FOLDER
ifs
INSTANCE
.init(
getInterface
= "00:16:D4:17:25:C4";
= "192.168.11.5";
= "D:/work/ttcnworkspace/com.fineqt.fpb.lib";
=
;
= 1;
FPB_HOME, FPB_PROTOCOL_FOLDER
INSTANCE
().name );
LOCAL_MAC, LOCAL_IP
INSTANCE
];
.getDeviceList();
.createPcapSocket();
);
);
表 4.2-1 SampleMain 类
3 行 本地物理 (MAC)地址的定义, Windows 下可以用“ ipconfig /all”命令取得。
http://code.google.com/p/fpb/
頁 16/65
Fine Packet Builder 快速入门
5 行 本地 IP(v4)地址的定义, Windows 下可以用“ ipconfig /all”命令取得。
6-10 行 定义 FPB 的安装目录及协议模块文件所在目录。安装目录是 FPB 安装文件解压缩后所在的目录,
而协议模块文件目录则是安装目录下的“ protocol”目录。
11-14 行 定义本机所有的网络接口描述对象数组,并指定使用哪个接口来进行通信。由于需要使
用链路层通信,所以通常指定物理上存在的网卡作为通信接口。可以将“ifs ”数组内的所有接口都打印出
来,然后与“ipconfig /all ”命令中列出的设备比对一下再决定使用哪个接口。
16-21 行 主函数。
24-37 行 ArpApp 类执行函数。
25 行 目标设备的 IP 地址,请求的就是 IP 地址与它相同的节点的 MAC 地址。
27 行 创建 Pcap 套接字。
28 行 设置通信所使用的网络设备(网卡)名称。
30 行 创建 ArpApp 对象。 LOCAL_MAC 和 LOCAL_IP 是常量,定义本地 MAC 和 IP 地址。
32 行 设置是否打印数据通信内容
34 行 执行 Arp 请求通信,取得目标设备的 MAC 地址。
36 行 打印执行结果。
41-46 行 取得本机的所有网络接口对象数组,并选择指定接口返回。
(b) SampleMain 类内 ArpApp 类使用例的执行结果例
Mac for 192.168.11.1 is 00:16:01:15:A4:88
(c) Arp 协议通信报文的打印例
• Arp Request 报文
0:42 EtherProtocol.EtherProtocol
0:6 dstAddress FF:FF:FF:FF:FF:FF
6:6 srcAddress 00:16:D4:17:25:C4
12:2 etherType 2054 ARP
14:28 payload
14:28 arp ArpProtocol.ArpProtocol
14:28 ArpProtocol.ArpProtocol
14:2 hwType 6 IEEE 802 Networks
16:2 protocolType 2048 IPv4
18:1 hlen 6 MAC
19:1 plen 4 IPv4
20:2 operation 1 Arp Request
22:6 senderHwAddress '0016D41725C4'O
28:4 senderProtocolAddress 'C0A80B05'O
32:6 targetHwAddress '000000000000'O
38:4 targetProtocolAddress 'C0A80B01'O
42:0 fcs omit
• Arp Response 报文
0:46 EtherProtocol.EtherProtocol
0:6 dstAddress 00:16:D4:17:25:C4
6:6 srcAddress 00:16:01:15:A4:88
12:2 etherType 2054 ARP
http://code.google.com/p/fpb/
頁 17/65
Fine Packet Builder 快速入门
14:28 payload
14:28 arp ArpProtocol.ArpProtocol
14:28 ArpProtocol.ArpProtocol
14:2 hwType 1 Ethernet - 10Mb
16:2 protocolType 2048 IPv4
18:1 hlen 6 MAC
19:1 plen 4 IPv4
20:2 operation 2 Arp Response
22:6 senderHwAddress '00160115A488'O
28:4 senderProtocolAddress 'C0A80B01'O
32:6 targetHwAddress '0016D41725C4'O
38:4 targetProtocolAddress 'C0A80B05'O
42:4 fcs '00000000'O
(d) ArpApp 类的源程序及说明
。。。
1
public class ArpApp {
2
private static IModule
3
.resolveModule("EtherProtocol");
4
private static IFactory
5
private static IValueSerializer
6
private String srcMac ;
7
private String srcIp ;
8
private IPcapSocket socket ;
9
private int timeout = ICommonSocket.
10
private boolean dumpPacket ;
11
12
/**
13
* 构造函数
14
* @param socket Pcap 套接字。
15
* @param srcMac 源设备的 MAC 地址。
16
* @param srcIp 源设备的 IP 地址。
17
*/
18
public ArpApp(IPcapSocket socket, String srcMac, String srcIp) {
19
this .socket = socket;
20
this .srcMac = srcMac;
21
this .srcIp = srcIp;
22
}
23
24
/**
25
* 生成 ARP 请求报文。协议栈为 Ehternet/Arp.
26
* @param dstIp
27
* @return
28
*/
29
private IRecordSetValue createArpRequest(String dstIp) throws MetaException {
30
// Ethernet
31
IRecordSetValue etherPrtl = (IRecordSetValue)
32
.createValue("EtherProtocol");
33
etherPrtl.getField("dstAddress").setTextAs( "ff:ff:ff:ff:ff:ff",
34
IValueTextStyle.
35
etherPrtl.getField("srcAddress").setTextAs(srcMac , IValueTextStyle.
36
etherPrtl.getField("etherType").setText( "0x0806");
37
module
factory
= IModuleRegistry.
=
module
ser
.getFactory();
= IValueSerializer.
DEFAULT_TIMEOUT
MAC_ADDRESS
);
INSTANCE
INSTANCE
factory
;
;
MAC_ADDRESS
);
http://code.google.com/p/fpb/
頁 18/65
Fine Packet Builder 快速入门
38
// Arp
39
IRecordSetValue arpPrtl = (IRecordSetValue) etherPrtl.findField("payload/arp",
40
true );
arpPrtl.getField("operation").setText( "1");
41
arpPrtl.getField("senderHwAddress")
42
.setTextAs(srcMac, IValueTextStyle.
43
arpPrtl.getField("senderProtocolAddress").setTextAs( srcIp,
44
IValueTextStyle.
45
arpPrtl.getField("targetHwAddress").setTextAs( "00:00:00:00:00:00",
46
IValueTextStyle.
47
arpPrtl.getField("targetProtocolAddress").setTextAs(dstIp,
48
IValueTextStyle.
49
return etherPrtl;
50
}
51
52
/**
53
* 根据目标设备的 IP 地址来取得目标设备的 MAC 地址。
54
* @param dstIp 目标设备的 IP 地址。
55
* @return 目标设备的 MAC 地址文本描述。
56
* @throws Exception
57
*/
58
public String askMac(String dstIp) throws Exception {
59
byte [] resData = new byte [1514];
60
socket .setTimeout(timeout );
61
// 打开套接字
62
socket .open();
63
try {
64
// 设置 Pcap 套接字的过滤条件。(过滤条件的书写规则可以参考 WinPcap 的用户手册)
65
socket .setFilter("ether dst " + srcMac + " and arp" , true );
66
// 生成 ARP 请求报文
67
IRecordSetValue arpRequest = createArpRequest(dstIp);
68
// 对报文数据包内的可计算字段进行自动计算(这里是 Arp 协议的 Hlen 和 Plen 字段)
69
ser
70
if (dumpPacket ) {
71
IValueDumper.
72
}
73
// 编码
74
byte data[] =
75
// 发送编码数据
76
socket .write(data);
77
// 接收应答数据
78
int len = socket .read(resData);
79
// 解码(底层协议为 Ethernet 所以使用 EtherProtocol 作为推测类型)
80
IRecordSetValue arpResponse = (IRecordSetValue) ProtocolUtils.
81
0, len,
82
// 打印解码后的 ARP 应答报文对象
83
if (dumpPacket ) {
84
IValueDumper.
85
}
86
// 从 EthernetProtocol 的 Payload 字段取得 ARP 协议字段
87
IRecordSetValue arpPrtl = (IRecordSetValue) arpResponse
88
.findField("payload/arp");
89
// 取得 ARP 协议的 SenderHwAddress 从而得到目标设备的 MAC 地址
90
return arpPrtl.getField("senderHwAddress" ).getTextAs(
91
http://code.google.com/p/fpb/
.calculate(arpRequest);
ser
IPV4_ADDRESS
MAC_ADDRESS
IPV4_ADDRESS
INSTANCE
.encode(arpRequest, false );
module
.getType("EtherProtocol" ));
INSTANCE
.dump(arpRequest);
.dump(arpResponse);
MAC_ADDRESS
);
);
);
);
decode
(resData,
頁 19/65
92
93
94
95
96
97
98
99
100
101
Fine Packet Builder 快速入门
IValueTextStyle.
} finally {
// 关闭套接字
socket .close();
}
}
。。。
}
3-4 行 用模块登记器( IModuleRegistry)取得以太网协议( EtherProtocol)。
5 行 取得值工厂对象。
6 行 取得值对象串行化器对象。
7 行 发送端 MAC 地址属性。
8 行 发送端 IP 地址属性。
MAC_ADDRESS
表 4.2-2 ArpApp 类
);
9 行 Pcap 套接字对象,用于链路层通信。
10 行 超时时间。
11 行 是否打印通信数据包。
19-23 行 构造函数。
30-51 行 创建 Arp 请求报文值对象函数的定义。
32-32 行 用值工厂 对象生成类型为 EtherProtocol 的值对象。
34-35 行 对于 EtherProtocol 的 dstAddress 字段,以文本方式设置 MAC 地址。值对象的
“getField ”方法用来取得容器值内的字段,“setTextAs ”方法则已指定的文本样式设置字段值,这里的
文本样式是 MAC_ADDRESS 即 MAC 地址。
37 行 用 setText 方法以文本形式设置字段的值。
39 行 用值对象的 findField方法按照指定路径取得对应字段。参数“ payload/arp ”表示路径为
EtherProtocol类型下的 payload字段下的arp字段。参数“true”表示指定路径上的字段为空或者omit
9
时
用默认值填充。
59-97 行 执行 Arp 请求函数的定义。
60 行 定义用于存放通信数据的字节数组。
61 行 设置 Pcap 套接字的超时时间。
63 行 打开套接字。
10
66 行 设置 Pcap套接字的过滤条件。因为FPB底层使用 WinPcap
来通信,所以过滤条件需按照
WinPcap的规则来书写。 ether dst XXX是指定目标 MAC地址为XXX。 arp是只收 ARP协议的数据包,也
就是指定 Ethernet协议的“类型”字段值为 0x0806。
9
字段可以是可选( optional)的,对于可选的字段使用 omit值来表示该字段不存在。
10
WinPcap是Pcap库的 Windows上的实现。而过滤条件表达式的书写规则可参照WinPcap用户指南的“过
滤串表达式的语法”章节。网上可以找到中文的翻译。
http://code.google.com/p/fpb/
頁 20/65