pcap使用手册
- 格式:doc
- 大小:66.00 KB
- 文档页数:9
WinPcap 教程: 循序渐进教您使用WinPcap本节将向您展示如何使用WinPcap API的一些特性。
这部分教程细化成若干节课,以循序渐进的方式介绍给读者,让读者从最基本的部分(获得设备列表)到最复杂的部分(控制发送队列并收集和统计网络流量)来了解如何使用WinPcap进行程序开发。
有时,我们会给出一些简单使用的代码片断,但同时,我们提供完整程序的链接:所有的源代码包含一些指向手册其他地方的链接,这可以让您很方便地通过点击鼠标来跳转到您想查看的函数和数据结构的内容中去。
范例程序都是用纯C语言编写, 所以,掌握基本的C语言编程知识是必须的,而且,这是一部关于处理原始网络数据包的教程,因为,我们希望读者拥有良好的网络及网络协议的知识。
用Microsoft Visual C++ 创建一个使用wpcap.dll 的应用程序,需要按一下步骤:∙在每一个使用了库的源程序中,将pcap.h 头文件包含(include)进来。
∙如果你在程序中使用了WinPcap中提供给Win32平台的特有的函数,记得在预处理中加入WPCAP 的定义。
(工程->设置->c/c++->预处理程序定义中添加WPCAP)∙如果你的程序使用了WinPcap的远程捕获功能,那么在预处理定义中加入HAVE_REMOTE。
不要直接把remote-ext.h直接加入到你的源文件中去。
(工程->设置->c/c++->预处理程序定义中添加HAVE_REMOTE)∙设置VC++的链接器(Linker),把wpcap.lib库文件包含进来。
wpcap.lib可以在WinPcap 中找到。
∙设置VC++的链接器(Linker),把ws2_32.lib库文件包含进来。
这个文件分布于C的编译器,并且包含了Windows的一些socket函数。
本教程中的一些范例程序,会需要它。
获取设备列表通常,编写基于WinPcap应用程序的第一件事情,就是获得已连接的网络适配器列表。
pcap使用手册让我们从看看这篇文章写给谁开始。
显而易见的,需要一些C语言基础知识,除非你只想了解基本的理论。
你不必是一个编码专家,因为这个领域只有经验丰富的程序员涉足,而我将尽可能详细的描述这些概念。
另外,考虑到这是有关一个包嗅探器的,所以对网络基础知识的理解是有帮助的。
所有在此出现的代码示例都已在FreeBSD 4.3平台上测试通过。
开始:pcap应用程序的格式我们所要理解的第一件事情是一个基于pcap的嗅探器程序的总体布局。
流程如下:1.我们从决定用哪一个接口进行嗅探开始。
在Linux中,这可能是eth0,而在BSD系统中则可能是xl1等等。
我们也可以用一个字符串来定义这个设备,或者采用pcap提供的接口名来工作。
2.初始化pcap。
在这里我们要告诉pcap对什么设备进行嗅探。
假如愿意的话,我们还可以嗅探多个设备。
怎样区分它们呢?使用文件句柄。
就像打开一个文件进行读写一样,必须命名我们的嗅探“会话”,以此使它们各自区别开来。
3.如果我们只想嗅探特定的传输(如TCP/IP包,发往端口23的包等等),我们必须创建一个规则集合,编译并且使用它。
这个过程分为三个相互紧密关联的阶段。
规则集合被置于一个字符串内,并且被转换成能被pcap读的格式(因此编译它)。
编译实际上就是在我们的程序里调用一个不被外部程序使用的函数。
接下来我们要告诉pcap使用它来过滤出我们想要的那一个会话。
4.最后,我们告诉pcap进入它的主体执行循环。
在这个阶段内pcap一直工作到它接收了所有我们想要的包为止。
每当它收到一个包就调用另一个已经定义好的函数,这个函数可以做我们想要的任何工作,它可以剖析所部获的包并给用户打印出结果,它可以将结果保存为一个文件,或者什么也不作。
5.在嗅探到所需的数据后,我们要关闭会话并结束。
这是实际上一个很简单的过程。
一共五个步骤,其中一个(第3个)是可选的。
我们为什么不看一看是怎样实现每一个步骤呢?设置设备这是很简单的。
Libpcap 是 Packet Capture library 的英文缩写,即数据包捕获函数库,该库提供的 C 函数接口用于捕获经过指定网络接口 (通过将网卡设置为混杂模式,可以捕获所有经过该网络接口的数据包 )的数据包。
著名的 TCPDUMP 就是在 Libpcap 的基础上开发而成的, Libpcap 提供的接口函数主要实现和封装了与数据包的采集、构造、发送等有关的功能。
Libpcap 面向上层应用,提供了用户级别的网络数据包捕获接口,在系统部署时充分考虑到应用程序的可以移植性。
Libpcap 主要有如下功能:(1)数据包捕获捕获流经本网卡的所有原始数据包,甚至对交换设备中的数据包也能够进行捕获,本功能是嗅探器的基础。
(2)自定义数据包发送构造任意格式的原始数据包,并发送到目标网络,本功能是新协议验证、甚至攻击验证的基础。
(3)流量采集与统计对所采集到的网络中的流量信息进行按照新规则分类,按指标进行统计,并输出到指定终端。
利用这项功能可以分析目标网络的流量特性。
(4)规则过滤Libpcap 自带规则过滤功能,并提供脚本编程接口,能够按照用户编程的方式对已经采集到的数据包进行过滤,以便提高分析的性能。
Libpcap 的应用范围:由于拥有强大的功能,当前基于 Libpcap 的应用比较广泛,有很多 Unix 上的流量相关的网络系统都是基于 Libpcap 的,它的一些典型应用如下:(1)网络协议分析器Libpcap 应用最多的就是网络协议分析器,也可以称之为网络嗅探。
(2)网络流量发生器网络流量发生器也是 Libpcap 的一大应用,它是基于 Libpcap 的数据构造与发送功能,可以有针对性的构造各种形式的数据包,并执行发送工作,这样的组合便构成了网络流量的产生工具。
(3)网络入侵检测系统网络入侵检测系统(IDS)是发现网络入侵行为的关键,利用 Libpcap 所提供的数据包捕获功能,可以进一步开发出 IDS。
pcap tls协议解析规则
摘要:
1.PCAP 简介
2.TLS 协议概述
3.PCAP 解析TLS 协议的方法
4.PCAP tls 协议解析规则的实际应用
5.总结
正文:
1.PCAP 简介
PCAP(Packet Capture) 是一种网络数据包捕获技术,可以用于监视和分析网络流量。
PCAP 可以捕获网络中的所有数据包,包括TLS 加密协议的数据包。
2.TLS 协议概述
TLS(Transport Layer Security) 是一种安全协议,用于保护网络通信。
TLS 协议通常用于保护Web 浏览器和Web 服务器之间的通信,以及其他需要保护数据传输的应用程序。
3.PCAP 解析TLS 协议的方法
PCAP 可以捕获TLS 协议的数据包,并通过解析这些数据包来获取TLS 协议的详细信息。
PCAP 可以使用各种工具来解析TLS 协议,例如Wireshark 和tcpdump。
4.PCAP tls 协议解析规则的实际应用
PCAP tls 协议解析规则可以用于监视和分析网络流量,以确保网络安全。
例如,可以使用PCAP tls 协议解析规则来检测TLS 协议的漏洞,并采取相应的措施来修复这些漏洞。
5.总结
PCAP 是一种强大的网络数据包捕获技术,可以用于监视和分析网络流量。
JNetPcap安装及使⽤啥是JNetPcap?JNetPcap是由开发的开源DPI(Deep Packet Inspection)SDK。
Java平台底层不⽀持底层⽹络操作,需要通过JNI封装不同系统提供的C库提供Java访问⽅法。
JnetPcap主要有下⾯四个特点:1. 提供⼏乎所有libpcap类的封装2. 实时解码抓取到的数据包3. 提供多种类的⽹络协议解析库4. 通过使⽤SDK⽤户可以轻松的扩展⽹络协议5. 通过native和Java实现,来优化解码过程JnetPcap安装JnetPcap的安装其实也⽐较简单,也就是3步⾛的政策。
关键有时候会搞不清楚,容易拉掉某些步骤。
因此,我将这些步骤整理如下:1. 安装依赖在第⼀部分对JNetPcap的介绍中已经提过了,JNetPcap⼏乎提供libpcap的所有封装,所以他肯定要依赖于libpcap的啦,通过⼀下命令在你的机器上安装libpcap。
yum install -y libpcap libpcap-devel2. 引⼊jar包引⼊jar包就是直接将jar包引⼊到你的项⽬中就可以了。
3. 设定library个⼈感觉这⼀步还是⽐较坑爹的,因为当你运⾏⼀个普通的java程序和运⾏⼀个hadoop MapReduce程序时,library的⽂件⽬录可能会有所不同。
你可以通过以下⽅法,查看当前java程序的library⽬录地址。
public class Main {public static void main() {// 输出当前程序的library⽬的地址System.out.println(System.getProperty("java.library.path"));}}然后将jnetpcap.so复制到上⾯输出的library⽬录中即可。
JNetPcap的相关demo参见。
参考⽂档1.。
实验3:WinPcap技术的使用1实验目的和要求学习使用WinPcap开发包实现网络数据包的捕获、过滤和分析的功能,具体要求如下:1)WinPcap开发包的下载和安装;2)使用WinPcap获取与网络适配器绑定的设备列表;3)使用WinPcap获取网络适配器的高级属性信息;4)使用WinPcap打开网络适配器并实现抓包功能5)使用WinPcap过滤数据包、分析数据包。
2实验设备及材料1)Windows主机2)Visual Studio 2005或Visual Studio 20083实验内容本实验学习WinPcap开发包的使用,利用WinPcap实现网络数据包捕获、过滤和分析的功能,实验内容如下。
3.1 WinPcap开发包的下载和安装下载并安装WinPcap开发包,下载地址:/archive/。
1)4.1.1-WinPcap.exe的安装;2)4.1.1-WpdPack.zip的下载和使用。
3.2获取与网络适配器绑定的设备列表信息pcap_findalldevs_ex()函数的使用。
调用pcap_findalldevs_ex()函数,获取的网络设备信息将存储在结构体pcap_if_t中,然后打印网卡设备列表信息,包括网络适配器名称和描述。
3.3获取网络适配器的高级属性信息在3.2的基础上,除打印本地主机所有网络适配器的名称、描述外,还打印是否回环地址、协议簇类型、协议簇名称、IP地址、子网掩码、广播地址和目标地址等信息。
3.4打开网络适配器并通过事件处理器来捕获数据包pcap_open()函数和pcap_loop()函数的使用。
程序的运行过程如下:1)调用pcap_findalldevs_ex()函数获取并打印本机的网络设备列表。
2)要求用户选择用于捕获数据包的网络设备。
3)使用for语句跳转到选中的网络设备,以便在后面的程序中打开该设备,并在该设备上捕获数据。
4)调用pcap_open()函数打开选择的网络设备。
Winpcap使用介绍Winpcap使用介绍Winpcap简介Winpcap(windowspacketcapture)是在Win32平台上的强大的、有较好扩展性的底层网络分析体系结构,是Unix下的lipbcap移植到windows下的产物,是Win32环境下数据包捕获的开放代码函数库。
Winpcap是第一个Win32开放式的捕获包的体系结构,能够支持大多数应用程序的需要。
如图A-1所示,Winpcap包含了一个内核级的数据包过滤器——NPF(NetgroupPacketFilter)、一个底层动态链接库(Packet.dll)和一个高层的独立于系统的库(Wpcap.dll)。
这三个模块中,NPF属于内核级,其他两模块属于用户级。
图A-1Winpcap的结构图NPF模块过滤数据包,将数据包不做任何改动的传递给用户,它还包含了一些操作系统专用代码(如:时间戳管理)。
Packet.dll模块提供了Win32平台下的捕获包的驱动接口。
实际上,不同版本的Windows都提供了不同的内核模块和应用程序之间的接口函数,Packet.dll有一套独立于系统的API来处理这些差异。
基于Packet.dll编写的程序可以不经过重新编译就在各种Win32平台下实现捕获数据包。
Packet.dll还包含了其他一些函数。
它可以进行一些底层的操作,Packet.dll和NPF都依赖于操作系统,并且由于Windows95/98和WindowsNT/2000之间操作系统结构的不同而在不同版本的操作系统上有所不同。
Wpcap.dll库不依赖于操作系统,并且它包含了一些其它高层的函数,比如:过滤器生成器、用户定义的缓冲区和高层特性(数据统计和构造数据包)。
Winpcap提供的功能包括四个方面:捕获原始数据包,包括在共享网络上各主机发送/接收的以及相互之间交换的数据包;在数据包发往应用程序之前,按照自定义的规则将某些特殊的数据包过滤掉;在网络上发送原始的数据包;收集网络通信过程中的流量信息。
pcap - Packet Capture librarySYNOPSIS大纲#include <pcap.h>char errbuf[PCAP_ERRBUF_SIZE];pcap_t *pcap_open_live(const char *device, int snaplen,int promisc, int to_ms,char *errbuf)pcap_t *pcap_open_dead(int linktype, int snaplen)pcap_t *pcap_open_offline(const char *fname, char *errbuf)pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname)int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf);int pcap_getnonblock(pcap_t *p, char *errbuf);int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)void pcap_freealldevs(pcap_if_t *alldevs)char *pcap_lookupdev(char *errbuf)int pcap_lookupnet(const char *device, bpf_u_int32 *netp,bpf_u_int32 *maskp, char *errbuf)int pcap_dispatch(pcap_t *p, int cnt,pcap_handler callback, u_char *user)int pcap_loop(pcap_t *p, int cnt,pcap_handler callback, u_char *user)void pcap_dump(u_char *user, struct pcap_pkthdr *h,u_char *sp)int pcap_compile(pcap_t *p, struct bpf_program *fp,char *str, int optimize,bpf_u_int32 netmask)int pcap_setfilter(pcap_t *p, struct bpf_program *fp)void pcap_freecode(struct bpf_program *);const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,const u_char**pkt_data)void pcap_breakloop(pcap_t *)int pcap_datalink(pcap_t *p)int pcap_list_datalinks(pcap_t *p, int **dlt_buf);int pcap_set_datalink(pcap_t *p, int dlt);int pcap_datalink_name_to_val(const char *name);const char *pcap_datalink_val_to_name(int dlt);const char *pcap_datalink_val_to_description(int dlt);int pcap_snapshot(pcap_t *p)int pcap_is_swapped(pcap_t *p)int pcap_major_version(pcap_t *p)int pcap_minor_version(pcap_t *p)int pcap_stats(pcap_t *p, struct pcap_stat *ps)FILE *pcap_file(pcap_t *p)int pcap_fileno(pcap_t *p)void pcap_perror(pcap_t *p, char *prefix)char *pcap_geterr(pcap_t *p)char *pcap_strerror(int error)const char *pcap_lib_version(void)void pcap_close(pcap_t *p)int pcap_dump_flush(pcap_dumper_t *p)FILE *pcap_dump_file(pcap_dumper_t *p)void pcap_dump_close(pcap_dumper_t *p)DESCRIPTIONThe Packet Capture library provides a high level interface to packet capture systems. All packets on the network, even those destined去往,注定for other hosts, are accessible可进入的,可及的through this mechanism.机械装置,原理ROUTINES函数NOTE: errbuf in pcap_open_live(), pcap_open_dead(), pcap_open_offline(), pcap_setnonblock(), pcap_getnonblock(), pcap_findalldevs(), pcap_lookupdev(), and pcap_lookupnet() is assumed假定的to be able to hold at leastPCAP_ERRBUF_SIZE chars.pcap_open_live() is used to obtain a packet capture descriptor to look at packets on the network. device is a string that specifies 指定的the network device to open; on Linux systems with 2.2 or later kernels, a device argument 参数,论点of "any" or NULL can be used to capture packets from all interfaces. snaplen specifies the maximum number of bytes to capture. If this value is less than the size of a packet that is captured, only the first snaplen bytes of that packet will be captured and provided as packet data. A value of 65535 should be sufficient, on most if not all networks, to capture all the data available from the packet. promisc specifies if the interface is to be put into promiscuous mode. (Note that even if this parameter参数is false, the interface could well be in promiscuous mode for some other reason.) For now, this doesn't work on the"any" device; if an argument of "any" or NULL is supplied, the promisc flag is ignored. to_ms specifies the read timeout in milliseconds. The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it wait for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms 平台support a read timeout; on platforms that don't, the read timeout is ignored. A zero value for to_ms, on platforms that support a read timeout, will cause a read to wait forever to allow enough packets to arrive, with no timeout. errbuf is used to return error or warning text. It will be set to error text when pcap_open_live() fails and returns NULL. errbuf may also be set to warning text when pcap_open_live() succeds; to detect this case the caller should store a zero-length string in errbuf before calling pcap_open_live() and display the warning to the user if errbuf is no longer a zero length string.pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char*ebuf)功能打开网卡参数char *device 指定的嗅探设备;snaplen pcap捕获的最大字节数;promisc 是否将指定接口设为为混杂模式;to_ms 读取时的超时值,单位是毫秒,如果为0则一直嗅探直到错误发生,为-1则不确定;。
PyShark 是一个用于处理Wireshark 抓包文件(pcap 文件)的Python 模块,它提供了一种以编程方式分析网络数据包的方法。
以下是一些PyShark 的基本使用手册:1. 安装PyShark:您可以使用`pip` 来安装PyShark:pip install pyshark2. 读取抓包文件:import pyshark# 指定抓包文件路径cap = pyshark.FileCapture('path/to/your/capture/file.pcap')# 遍历所有数据包for packet in cap:print(packet)3. 访问数据包字段:import pysharkcap = pyshark.FileCapture('path/to/your/capture/file.pcap')for packet in cap:# 获取协议类型protocol = packet.transport_layer# 获取源和目标IP 地址src_ip = packet.ip.srcdst_ip = packet.ip.dst# 获取源和目标端口src_port = packet[packet.transport_layer].srcportdst_port = packet[packet.transport_layer].dstport# 打印相关信息print(f"Protocol: {protocol}, Source: {src_ip}:{src_port}, Destination: {dst_ip}:{dst_port}")4. 过滤数据包:import pysharkcap = pyshark.FileCapture('path/to/your/capture/file.pcap', display_filter='http') for packet in cap:print(packet)5. 读取实时抓包:import pyshark# 实时抓包live_cap = pyshark.LiveCapture(interface='your_network_interface')# 遍历实时抓包for packet in live_cap.sniff_continuously(packet_count=10):print(packet)这只是PyShark 的基本使用示例。
WinPcap 教程: 循序渐进教您使用WinPcap本节将向您展示如何使用WinPcap API的一些特性。
这部分教程细化成若干节课,以循序渐进的方式介绍给读者,让读者从最基本的部分(获得设备列表)到最复杂的部分(控制发送队列并收集和统计网络流量)来了解如何使用WinPcap进行程序开发。
有时,我们会给出一些简单使用的代码片断,但同时,我们提供完整程序的链接:所有的源代码包含一些指向手册其他地方的链接,这可以让您很方便地通过点击鼠标来跳转到您想查看的函数和数据结构的内容中去。
范例程序都是用纯C语言编写, 所以,掌握基本的C语言编程知识是必须的,而且,这是一部关于处理原始网络数据包的教程,因为,我们希望读者拥有良好的网络及网络协议的知识。
用Microsoft Visual C++ 创建一个使用wpcap.dll 的应用程序,需要按一下步骤:∙在每一个使用了库的源程序中,将pcap.h 头文件包含(include)进来。
∙如果你在程序中使用了WinPcap中提供给Win32平台的特有的函数,记得在预处理中加入WPCAP 的定义。
(工程->设置->c/c++->预处理程序定义中添加WPCAP)∙如果你的程序使用了WinPcap的远程捕获功能,那么在预处理定义中加入HAVE_REMOTE。
不要直接把remote-ext.h直接加入到你的源文件中去。
(工程->设置->c/c++->预处理程序定义中添加HAVE_REMOTE)∙设置VC++的链接器(Linker),把wpcap.lib库文件包含进来。
wpcap.lib可以在WinPcap 中找到。
∙设置VC++的链接器(Linker),把ws2_32.lib库文件包含进来。
这个文件分布于C的编译器,并且包含了Windows的一些socket函数。
本教程中的一些范例程序,会需要它。
获取设备列表通常,编写基于WinPcap应用程序的第一件事情,就是获得已连接的网络适配器列表。
Winpcap 程序员手册Packet.dll API :程序员手册1.介绍PACKET.DLL 是一个动态连接库。
它提供了一套面向用户的包捕捉驱动程序接口。
这套动态连接库实现了一系列的函数,使得用户与驱动器的通信变得更为简便。
这避免了在用户程序中使用系统调用或控制输入/输出设备驱动模式(IOCTLs)。
而且,这套动态连接库还提供了网络适配器控制函数,对网络上捕获的数据包进行读取/写入函数,在驱动器中设置缓冲区和过滤器函数等等。
目前,有两个版本的PACKET.DLL:第一个适用于Windows95/98,第二个版本适用于WindowsNT/2000。
这两个版本都提供了相同的应用程序接口,这使得编写独立于系统的包捕获应用程序变得更为容易。
通过调用PACKET.DLL API,同一个应用程序可不做任何修改就在Windows95/98/NT/2000环境下运行。
本手册讲述了如何使用PACKET.DLL,并详细讲解这套动态连接库提供的函数和数据结构。
2.PACKET.DLL 与wpcap的比较如果你要编写一个没有特别/底层要求的包捕获应用程序,推荐使用wpcap.dll的函数,这是包捕获库(libpcap)的一个扩展集,而不是本章节中讨论的API。
在wpcap.dll中也使用PACKET.DLL的函数。
但wpcap.dll提供了一个更强大、更直接、更简洁的编程环境。
通过使用wpcap.dll,诸如捕获包、创建一个包过滤器或者在文件中保存dump 这些操作会被准确地执行并使程序变得直观。
Libpcap能够为一个标准的网络监听或嗅探程序提供所有需要的函数。
而且,利用libpcap编写的程序也能在UNIX平台上进行编译,这是因为这个库的Win32版本和UNIX版本有很好的兼容性。
然而,PACKET.DLL API 有一些libpcap没有提供的可能的操作。
Libpcap相对简单,它提供了一套系统无关的捕获包的API。
Winpcap的安装使用方法winpcap的安装包,然后到2.执行安装包,这样你的机子就能运行winpcap 程序了。
3.解压开发包,在VC6.0的Tools-->Option-->Directories的Include fils 和library files加入winpcap的include和lib目录。
4.开始编写wpcap程序。
vs2005:第一步:下载WinPcap的安装包;有不同操作系统环境下的包,我下的是win32版本的。
下载地址:高的版本一般是Beta的。
这个安装包主要是注册一个wpcap.dll的库到操作系统中。
必须安装,如果不安装,在运行例子的时候会弹出窗口提示,找不到wpcap.dll文件;第二步:到上面的网站下载它的开发包,包括一些头文件和库文件;解压到自己指定的目录中;目录中还有HTML格式的说明文档,用于自己学习比较方便;第三步:设置VS2005;1)设置环境目录;在菜单:工具->选项;弹出的选项窗体左边点击:项目和解决方案->VC++目录;在右边:“显示以下内容的目录”标签下面的下拉框中找到“包含文件”,然后对应到第二步下载开发包的Include目录;在同一下拉框中找到“库文件”,然后对应到第二步下载开发包的lib目录;2)设置编译条件;在项目属性页中:配置属性->C/C++->预处理器->预处理器定义,增加;WPCAP;HAVE_REMOTE;每一个预定义符用";"隔开;在项目属性页中:配置属性->链接器->命令行->附加选项对应的文本框中增加:“wpcap.libws2_32.lib”;第四步:非必要步骤;有的时候可能会有些意外错误;比如找不到u_char类型等;我的解决办法是加上#ifndef WIN32#include <sys/socket.h>#include <netinet/in.h>#else#include <winsock.h>#endif============================================= ====================================winpcap开发包使用中的问题总结这里主要讨论一下winpcap开发中可能遇到的问题。
pcap简单使⽤和简单解释数据类型bpf_u_int32实际上就是u_int的⼀个别名,还有吧bpf_int32实际上就是int的别名。
当然这个int是32位的,如果操作系统对int的定义不是4字节,bpf_int32就对应另外⼀种类型,总之,bpf_u_int32就是⼀个32位的⽆符号整型。
关键函数:int pcap_lookupnet(const char *device, bpf_u_int32 *netp,bpf_u_int32 *maskp, char *errbuf)⽤于获取⽹卡的⽹络号和⼦⽹掩码。
其中device参数是⽹卡名,netp 和maskp表⽰将要获得的⽹络号和⼦⽹掩码,都是以⽹络字节序存放的,⽐如⼀个IP为10.108.20.0,那么netp中存放的这个地址就是:1338378。
转换成⼆进制就是:00000000 00010100 01101100 00001010这个数在内存中的存在形式就是:低地址----------------------------------------》⾼地址00001010 01101100 00010100 00000000对应每个字节的⼗进制就是:10 108 20 0⽹络字节序和主机字节序⽐较容易混乱(⼤端表⽰和⼩端表⽰)。
⽹络字节序采⽤⼤端表⽰,就是数据的⾼位要存放到低地址。
⽽⼤多数主机字节序采⽤⼩端表⽰(也有采⽤⼤端表⽰的主机字节序),就是数据的低位放到低地址。
⽐如⽆符号整型1338378,的⼆进制表⽰为:数据的⾼位----------------------------》数据的低位00000000 00010100 01101100 00001010所以采⽤⼩端表⽰的主机字节序时,内存中存放的形式为:低地址----------------------------------------》⾼地址00001010 01101100 00010100 00000000errbuf存放错误信息。
libpcap使⽤(1)0x00 Libpcap介绍Libpcap是⼀个开源库,它为⽹络数据包捕获提供了⼀个⾼级接⼝。
Libpcap作者的主要⽬标是创建⼀个独⽴于平台的API,以消除对每个应⽤程序中依赖于系统的数据包捕获模块的需求,因为⼏乎每个操作系统供应商都实现了⾃⼰的捕获机制.libpcap的API被设计⽤来供C和C++使⽤,然后有许多包装器,也可以让 Perl,Python Java C# or Ruby 使⽤。
libpcap能在⼤多数类unix的操作系统上。
还有⼀个名为Winpcap的Windows版本。
如今,libpcap由tcpdump⼩组维护。
0x01 使⽤Libpcap的第⼀步1.我们⾸先需要⼀个⽹络接⼝监听char *pcap_lookupdev(char *errbuf)/*1. 函数返回⼀个指针,该指针指向⼀个字符串,该字符串包含适合包捕获的第⼀个⽹络设备的名称2. errbuf参数是⽤户提供⽤来存储错误信息的*/通常,当最终⽤户没有指定任何⽹络接⼝时,调⽤此函数⽹络接⼝。
使⽤硬编码接⼝名通常是⼀个坏主意,因为它们通常不能跨平台移植。
libpcap实现的许多函数都使⽤errbuf这个参数,⽤来获取错误。
在分配缓冲区时我们必须⼩⼼,因为它必须⾄少能够容纳 PCAP_ERRBUF_SIZE 这么多字节。
我们可以使⽤PCAP_ERRBUF_SIZE这个宏来作为数组的⼤⼩。
2. 打开获取的⽹络接⼝pcap_t *pcap_open_live(const char *device, int snaplen, int promise, int to_ms, char *errbuf)/*参数:1. 该函数的第⼀参数是⼀个字符串,包含要打开⽹络接⼝的名称。
2. 第⼆个参数是要捕获的最⼤字节数。
如果我们只对获取数据头感兴趣或者有限制内存的嵌⼊式编程,那么可以为第⼆个参数设置⼀个较低的值。
3. 第三个参数promise 标志决定了⽹络接⼝是否应该进⼊混杂模式,混杂模式是说⽹卡可以接收不是该⽹卡⽬的地的数据包。
一些需要知道的细节描述(前言):这一部分展示了如何使用WINPC AP-API的不同的功能,它作为一个使用指南被划分为一系列的课时来带领读者循序渐进的体会PCAP的程序设计的魅力:从简单的基本功能(如获取网卡的列表,数据包的捕获等)到统计和收集网络流量等高级功能。
在这里将提供一些简单但完整的代码作为参考:所有的这些原代码都有和它相关的详细信息的连接以便单击这些功能和数据结构时能够即使跳转到相关的文献。
这些例子是用C语言写的,所以在学习之前首先要有一定的C语言的基础,当然PCAP作为一个网络底层的驱动,要想学好它也必须具备一定的网络方面的知识。
(一)得到网络驱动列表用PCAP写应用程序的第一件事往往就是要获得本地的网卡列表。
PCAP提供了pcap_find allde vs()这个函数来实现此功能,这个API返回一个 pcap_i f结构的连表,连表的每项内容都含有全面的网卡信息:尤其是字段名字和含有名字的描述以及有关驱动器的易读信息。
得到网络驱动列表的程序如下:程序代码: [ 复制代码到剪贴板 ]#includ e "pcap.h"main(){pcap_i f_t *alldev s;pcap_i f_t *d;int i=0;char errbuf[PCAP_E RRBUF_SIZE];/* 这个API用来获得网卡的列表 */if (pcap_f indal ldevs(&alldev s, errbuf) == -1){fprint f(stderr,"Errorin pcap_f indal ldevs: %s\n", errbuf);exit(1);}/* 显示列表的响应字段的内容 */for(d=alldev s;d;d=d->next){printf("%d. %s", ++i, d->name);if (d->descri ption)printf(" (%s)\n", d->descri ption);else printf(" (No descri ption availa ble)\n");}if(i==0){printf("\nNo interf acesfound! Make sure WinPca p is instal led.\n"); return;}/* We don‘t need any more the device list. Free it */pcap_f reeal ldevs(alldev s);}[code]有关这段程序的一些说明:首先pcap_find allde vs()同其他的li bpcap函数一样有一个err buf参数,当有异常情况发生时,这个参数会被PCAP填充为某个特定的错误字串。
WinpCap的详解(一)首先来百科一下Winpcap是一个什么东东。
Winpcap(windows packet capture)是windows平台下一个免费,公共的网络访问系统。
它有如下几个功能:1、捕获原始数据包,包括在共享网络上各主机发送/接收的以及相互之间交换的数据;2、在数据包发往应用程序之前,按照自定义的规则将某些特殊的数据包过滤掉;3、在网络上发送原始的数据包;4、收集网络通信过程中的统计信息。
从上面的功能来看,这个库文件提供了许多的API函数,可以让我们捕获网络上的数据包以及统计网络通信的信息。
为了更直观的反应这个库文件的作用,我们来看看利用这个库文件写出来的一个应用软件,wireshark。
界面如下图所示,这个界面只是捕获数据的一个小界面,里面有很多的设置,有兴趣可以下载一个试试。
他能统计在一个局域网的所有网络信息。
这里面重要一点,需要提醒的是:winpcap的主要功能在于独立于主机协议(如TCP-IP)而发送和接收原始数据包。
也就是说,winpcap不能阻塞,过滤或控制其他应用程序数据包的发收,它仅仅只是监听共享网络上传送的数据包。
也就是说,WinpCap主要功能不能截取网络中的数据,他只能监听里面的数据。
对于WinpCap的结构以及原理,我们自然可以不用理会啦,我们只需要知道他的用途就行啦!一、安装WinpCap1、首先我们来看看如何安装WinpCap这个库,首先是下载WinpCap安装文件,这里有许多的版本,可以在官网上下载,,这里重点提醒一下,特别需要注意一下版本,如果你的版本是4.02,那么你的安装包也必须下载对应的版本,这里特别注意下,你可以下载当前比较稳定的版本。
下载之后安装就ok啦!这里我用的是WinpCap4.02.2、下载WinpCap Develop's Packs,这里我也提供相同的版本WpdPack4.02.3、解压后会得一个目录WpdPack四个子目录:docsExamples-pcapExamples-remoteIncludeLib然后配置VC++tools --> options --> Projects and Solutions --> VC++ Directories :Include files :WpdPackPath\includeLibrary files:WpdPackPath\lib4、经过上面的步骤之后,你的WinpCap应该就安装成功啦,之后就是运行一下里面提供的例程啦,如果有什么问题,就对应的把问题在网上查一查,总体来说有以下几个问题:第一个就是需要在工程的链接库上添加wpcap.lib链接库;第二个就是你的SDK太老了,需要添加更新你的SDK,相应的到官方网站上下载适合你电脑的SDK。
PCAPSection: C Library Functions (3)Updated: 21 November 2003[INDEX]From: /NAMEpcap - Packet Capture libraryDescriptionThe Packet Capture library provides a high level interface to packet capture systems. All packets on the network, even those destined for other hosts, are accessible through this mechanism.Edited by Rhett, SJTU, 2011APIs1.char errbuf[PCAP_ERRBUF_SIZE];2.pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf)3.pcap_t *pcap_open_dead(int linktype, int snaplen)4.pcap_t *pcap_open_offline(const char *fname, char *errbuf)5.pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname)6.int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf);7.int pcap_getnonblock(pcap_t *p, char *errbuf);8.int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)9.void pcap_freealldevs(pcap_if_t *alldevs)10.char *pcap_lookupdev(char *errbuf)11.int pcap_lookupnet(const char *device, bpf_u_int32 *netp,bpf_u_int32 *maskp, char *errbuf)12.int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)13.int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)14.void pcap_dump(u_char *user, struct pcap_pkthdr *h, u_char *sp)15.int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32netmask)16.int pcap_setfilter(pcap_t *p, struct bpf_program *fp)17.void pcap_freecode(struct bpf_program *);18.const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)19.int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data)20.void pcap_breakloop(pcap_t *)21.int pcap_datalink(pcap_t *p)22.int pcap_list_datalinks(pcap_t *p, int **dlt_buf);23.int pcap_set_datalink(pcap_t *p, int dlt);24.int pcap_datalink_name_to_val(const char *name);25.const char *pcap_datalink_val_to_name(int dlt);26.const char *pcap_datalink_val_to_description(int dlt);27.int pcap_snapshot(pcap_t *p)28.int pcap_is_swapped(pcap_t *p)29.int pcap_major_version(pcap_t *p)30.int pcap_minor_version(pcap_t *p)31.int pcap_stats(pcap_t *p, struct pcap_stat *ps)32.FILE *pcap_file(pcap_t *p)33.int pcap_fileno(pcap_t *p)34.void pcap_perror(pcap_t *p, char *prefix)35.char *pcap_geterr(pcap_t *p)36.char *pcap_strerror(int error)37.const char *pcap_lib_version(void)38.void pcap_close(pcap_t *p)39.int pcap_dump_flush(pcap_dumper_t *p)40.FILE *pcap_dump_file(pcap_dumper_t *p)41.void pcap_dump_close(pcap_dumper_t *p)Definition#include <pcap.h>char errbuf[PCAP_ERRBUF_SIZE]; [INDEX]NOTE: errbuf in pcap_open_live(), pcap_open_dead(), pcap_open_offline(), pcap_setnonbl ock(),pcap_getnonblock(), pcap_findalldevs(), pcap_lookupdev(),and pcap_lookupnet() is assumed to be able to hold at least PCAP_ERRBUF_SIZE chars.pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf) [INDEX]pcap_open_live() is used to obtain a packet capture descriptor to look at packets on the network. device is a string that specifies the network device to open; on Linux systems with2.2 or later kernels, a device argument of "any" or NULL can be used to capture packets fromall interfaces. snaplen specifies the maximum number of bytes to capture. If this value is less than the size of a packet that is captured, only the first snaplen bytes of that packet will be captured and provided as packet data. A value of 65535 should be sufficient, on most if not all networks, to capture all the data available from the packet. promisc specifies if the interface is to be put into promiscuous mode. (Note that even if this parameter is false, the interface could well be in promiscuous mode for some other reason.) For now, this doesn't work on the "any" device; if an argument of "any" or NULL is supplied, the promisc flag is ignored. to_ms specifies the read timeout in milliseconds. The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it wait for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms support a read timeout; on platforms that don't, the read timeout is ignored. A zero value forto_ms, on platforms that support a read timeout, will cause a read to wait forever to allow enough packets to arrive, with no timeout. errbuf is used to return error or warning text. It will be set to error text when pcap_open_live() fails and returns NULL. errbuf may also be set to warning text when pcap_open_live()succeds; to detect this case the caller should store a zero-length string in errbuf before calling pcap_open_live() and display the warning to the user if errbuf is no longer a zero-length string.pcap_t *pcap_open_dead(int linktype, int snaplen) [INDEX]pcap_open_dead() is used for creating a pcap_t structure to use when calling the other functions in libpcap. It is typically used when just using libpcap for compiling BPF code.pcap_t *pcap_open_offline(const char *fname, char *errbuf) [INDEX]pcap_open_offline() is called to open a ``savefile'' for reading. fname specifies the name of the file to open. The file has the same format as those used by tcpdump(1) and tcpslice(1). The name "-" in a synonym for stdin. errbuf is used to return error text and is only set when pcap_open_offline() fails and returns NULL.pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname)[INDEX]pcap_dump_open() is called to open a ``savefile'' for writing. The name "-" in a synonym for stdout. NULL is returned on failure. p is a pcap struct as returned by pcap_open_offline() or pcap_open_live(). fname specifies the name of the file to open. If NULL is returned, pcap_geterr() can be used to get the error text.int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf); [INDEX]pcap_setnonblock() puts a capture descriptor, opened with pcap_open_live(), into ``non-blocking'' mode, or takes it out of ``non-blocking'' mode, depending on whether the nonblock argument is non-zero or zero. It has no effect on ``savefiles''. If there is an error, -1 is returned and errbuf is filled in with an appropriate error message; otherwise, 0 is returned. In ``non-blocking'' mode, an attempt to read from the capture descriptor with pcap_dispatch() will, if no packets are currently available to be read, return 0 immediately rather than blocking waiting for packets to arrive. pcap_loop() and pcap_next() will not work in ``non-blocking'' mode.int pcap_getnonblock(pcap_t *p, char *errbuf); [INDEX]pcap_getnonblock() returns the current ``non-blocking'' state of the capture descriptor; it always returns 0 on ``savefiles''. If there is an error, -1 is returned and errbuf is filled in with an appropriate error message.int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) [INDEX]pcap_findalldevs() constructs a list of network devices that can be opened with pcap_open_live(). (Note that there may be network devices that cannot be opened with pcap_open_live() by the process calling pcap_findalldevs(), because, for example, that process might not have sufficient privileges to open them for capturing; if so, those devices will not appear on the list.) alldevsp is set to point to the first element of the list; each element of the list is of type pcap_if_t, and has the following members:nextif not NULL, a pointer to the next element in the list; NULL for the last elementof the listnamea pointer to a string giving a name for the device to pass to pcap_open_live()descriptionif not NULL, a pointer to a string giving a human-readable description of thedeviceaddressesa pointer to the first element of a list of addresses for the interfaceflagsinterface flags:PCAP_IF_LOOPBACKset if the interface is a loopback interfaceEach element of the list of addresses is of type pcap_addr_t, and has the following members:nextif not NULL, a pointer to the next element in the list; NULL for the last elementof the listaddra pointer to a struct sockaddr containing an addressnetmaskif not NULL, a pointer to a struct sockaddr that contains the netmaskcorresponding to the address pointed to by addrbroadaddrif not NULL, a pointer to a struct sockaddr that contains the broadcast addresscorresponding to the address pointed to by addr;may be null if the interfacedoesn't support broadcastsdstaddrif not NULL, a pointer to a struct sockaddr that contains the destination addresscorresponding to the address pointed to by addr; may be null if the interfaceisn't a point-to-point interface-1 is returned on failure, in which case errbuf is filled in with an appropriate error message; 0 is returned on success.void pcap_freealldevs(pcap_if_t *alldevs) [INDEX]pcap_freealldevs() is used to free a list allocated by pcap_findalldevs().char *pcap_lookupdev(char *errbuf) [INDEX]pcap_lookupdev() returns a pointer to a network device suitable for use with pcap_open_live() and pcap_lookupnet(). If there is an error, NULL is returned and errbuf is filled in with an appropriate error message.int pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf) [INDEX]pcap_lookupnet() is used to determine the network number and mask associated with the network device device. Both netp and maskp are bpf_u_int32 pointers. A return of -1 indicates an error in which case errbuf is filled in with an appropriate error message.int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) [INDEX]pcap_dispatch() is used to collect and process packets. cnt specifies the maximum number of packets to process before returning. This is not a minimum number; when reading a live capture, only one bufferful of packets is read at a time, so fewer than cnt packets may be processed. A cnt of -1 processes all the packets received in one buffer when reading a live capture, or all the packets in the file when reading a ``savefile''. callback specifies a routine to be called with three arguments: a u_char pointer which is passed in from pcap_dispatch(), a const struct pcap_pkthdr pointer to a structure with the following members:tsa struct timeval containing the time when the packet was capturedcaplena bpf_u_int32 giving the number of bytes of the packet that are available fromthe capturelena bpf_u_int32 giving the length of the packet, in bytes (which might be morethan the number of bytes available from the capture, if the length of the packetis larger than the maximum number of bytes to capture)and a const u_char pointer to the first caplen (as given in the struct pcap_pkthdr a pointer to which is passed to the callback routine) bytes of data from the packet (which won't necessarily be the entire packet; to capture the entire packet, you will have to provide a value for snaplen in your call to pcap_open_live() that is sufficiently large to get all of the packet's data - a value of 65535 should be sufficient on most if not all networks).The number of packets read is returned. 0 is returned if no packets were read from a live capture (if, for example, they were discarded because they didn't pass the packet filter, or if, on platforms that support a read timeout that starts before any packets arrive, the timeout expires before any packets arrive, or if the file descriptor for the capture device is in non-blocking mode and no packets were available to be read) or if no more packets are available in a “savefile.”A return of -1 indicates an error in which case pcap_perror() or pcap_geterr() may be used to display the error text. A return of -2 indicates that the loop terminated due to a call to pcap_breakloop() before any packets were processed. If your application uses pcap_breakloop(), make sure that you explicitly check for -1 and -2, rather than just checking for a return value < 0.NOTE: when reading a live capture, pcap_dispatch() will not necessarily return when the read times out; on some platforms, the read timeout isn't supported, and, on otherplatforms, the timer doesn't start until at least one packet arrives. This means that the read timeout should NOT be used in, for example, an interactive application, to allow the packet capture loop to ``poll'' for user input periodically, as there's no guarantee thatpcap_dispatch() will return after the timeout expires.int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) [INDEX]pcap_loop() is similar to pcap_dispatch() except it keeps reading packets until cnt packets are processed or an error occurs. It does not return when live read timeouts occur. Rather, specifying a non-zero read timeout to pcap_open_live() and then calling pcap_dispatch() allows the reception and processing of any packets that arrive when the timeout occurs. A negative cnt causes pcap_loop() to loop forever (or at least until an error occurs). -1 is returned on an error; 0 is returned if cnt is exhausted; -2 is returned if the loop terminated due to a call to pcap_breakloop() before any packets were processed. If your application uses pcap_breakloop(), make sure that you explicitly check for -1 and -2, rather than just checking for a return value < 0.void pcap_dump(u_char *user, struct pcap_pkthdr *h, u_char *sp)[INDEX]pcap_dump() outputs a packet to the ``savefile'' opened with pcap_dump_open(). Note that its calling arguments are suitable for use with pcap_dispatch() or pcap_loop(). If called directly, the user parameter is of type pcap_dumper_t as returned by pcap_dump_open().int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask) [INDEX]pcap_compile() is used to compile the string str into a filter program. program is a pointer to a bpf_program struct and is filled in by pcap_compile(). optimize controls whether optimization on the resulting code is performed. netmask specifies the IPv4 netmask of the network on which packets are being captured; it is used only when checking for IPv4 broadcast addresses in the filter program. If the netmask of the network on which packets are being captured isn't known to the program, or if packets are being captured on the Linux "any" pseudo-interface that can capture on more than one network, a value of 0 can be supplied; tests for IPv4 broadcast addresses won't be done correctly, but all other tests in the filter program will be OK. A return of -1 indicates an error in which case pcap_geterr() may be used to display the error text.pcap_compile_nopcap() is similar to pcap_compile() except that instead of passing a pcap structure, one passes the snaplen and linktype explicitly. It is intended to be used for compiling filters for direct BPF usage, without necessarily having called pcap_open(). A return of -1 indicates an error; the error text is unavailable. (pcap_compile_nopcap() is a wrapper around pcap_open_dead(), pcap_compile(), and pcap_close(); the latter three routines can be used directly in order to get the error text for a compilation error.)int pcap_setfilter(pcap_t *p, struct bpf_program *fp) [INDEX]pcap_setfilter() is used to specify a filter program. fp is a pointer to a bpf_program struct, usually the result of a call to pcap_compile(). -1 is returned on failure, in which case pcap_geterr() may be used to display the error text; 0 is returned on success.void pcap_freecode(struct bpf_program *); [INDEX]pcap_freecode() is used to free up allocated memory pointed to by a bpf_program struct generated by pcap_compile() when that BPF program is no longer needed, for example after it has been made the filter program for a pcap structure by a call to pcap_setfilter().const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h) [INDEX]pcap_next() reads the next packet (by calling pcap_dispatch() with a cnt of 1) and returns a u_char pointer to the data in that packet. (The pcap_pkthdr struct for that packet is not supplied.) NULL is returned if an error occured, or if no packets were read from a live capture (if, for example, they were discarded because they didn't pass the packet filter, or if, on platforms that support a read timeout that starts before any packets arrive, the timeout expires before any packets arrive, or if the file descriptor for the capture device is in non-blocking mode and no packets were available to be read), or if no more packets are available in a ``savefile.'' Unfortunately, there is no way to determine whether an error occured or not.int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data) [INDEX]pcap_next_ex() reads the next packet and returns a success/failure indication:1the packet was read without problemspackets are being read from a live capture, and the timeout expired -1an error occurred while reading the packet-2packets are being read from a ``savefile'', and there are no more packets to readfrom the savefile.If the packet was read without problems, the pointer pointed to by the pkt_header argument is set to point to the pcap_pkthdr struct for the packet, and the pointer pointed to by the pkt_data argument is set to point to the data in the packet.void pcap_breakloop(pcap_t *) [INDEX]pcap_breakloop() sets a flag that will force pcap_dispatch() or pcap_loop() to return rather than looping; they will return the number of packets that have been processed so far, or -2 if no packets have been processed so far.This routine is safe to use inside a signal handler on UNIX or a console control handler on Windows, as it merely sets a flag that is checked within the loop.The flag is checked in loops reading packets from the OS - a signal by itself will not necessarily terminate those loops - as well as in loops processing a set of packets returned by the OS. Note that if you are catching signals on UNIX systems that support restarting system calls after a signal, and calling pcap_breakloop() in the signal handler, you must specify, when catching those signals, that system calls should NOT be restarted by that signal. Otherwise, if the signal interrupted a call reading packets in a live capture, when your signal handler returns after calling pcap_breakloop(), the call will be restarted, and the loop will not terminate until more packets arrive and the call completes.Note that pcap_next() will, on some platforms, loop reading packets from the OS; that loop will not necessarily be terminated by a signal, so pcap_breakloop() should be used to terminate packet processing even if pcap_next() is being used.pcap_breakloop() does not guarantee that no further packets will be processed by pcap_dispatch() or pcap_loop() after it is called; at most one more packet might be processed.If -2 is returned from pcap_dispatch() or pcap_loop(), the flag is cleared, so a subsequent call will resume reading packets. If a positive number is returned, the flag is not cleared, so a subsequent call will return -2 and clear the flag.int pcap_datalink(pcap_t *p) [INDEX]pcap_datalink() returns the link layer type; link layer types it can return include:DLT_NULLBSD loopback encapsulation; the link layer header is a 4-byte field, in host byte order, containing a PF_ value from socket.h for the network-layer protocol of the packet.Note that ``host byte order'' is the byte order of the machine on which the packets are captured, and the PF_ values are for the OS of the machine on which the packets are captured; if a live capture is being done, ``host byte order'' is the byte order of the machine capturing the packets, and the PF_ values are those of the OS of the machine capturing the packets, but if a ``savefile'' is being read, the byte order and PF_ values are not necessarily those of the machine reading the capture file.DLT_EN10MBEthernet (10Mb, 100Mb, 1000Mb, and up)DLT_IEEE802IEEE 802.5 Token RingDLT_ARCNETARCNETDLT_SLIPSLIP; the link layer header contains, in order:a 1-byte flag, which is 0 for packets received by the machine and 1 for packets sentby the machine;a 1-byte field, the upper 4 bits of which indicate the type of packet, as per RFC1144:0x40an unmodified IP datagram (TYPE_IP);0x70an uncompressed-TCP IP datagram (UNCOMPRESSED_TCP), with thatbyte being the first byte of the raw IP header on the wire, containing theconnection number in the protocol field;0x80a compressed-TCP IP datagram (COMPRESSED_TCP), with that bytebeing the first byte of the compressed TCP/IP datagram header;for UNCOMPRESSED_TCP, the rest of the modified IP header, and for COMPRESSED_TCP, the compressed TCP/IP datagram header;for a total of 16 bytes; the uncompressed IP datagram follows the header.DLT_PPPPPP; if the first 2 bytes are 0xff and 0x03, it's PPP in HDLC-like framing, with the PPP header following those two bytes, otherwise it's PPP without framing, and the packet begins with the PPP header.DLT_FDDIFDDIDLT_ATM_RFC1483RFC 1483 LLC/SNAP-encapsulated ATM; the packet begins with an IEEE 802.2 LLC header.DLT_RAWraw IP; the packet begins with an IP header.DLT_PPP_SERIALPPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547; the first byte will be 0xFF for PPP in HDLC-like framing, and will be 0x0F or 0x8F for Cisco PPP with HDLC framing.DLT_PPP_ETHERPPPoE; the packet begins with a PPPoE header, as per RFC 2516.DLT_C_HDLCCisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547.DLT_IEEE802_11IEEE 802.11 wireless LANDLT_FRELAYFrame RelayDLT_LOOPOpenBSD loopback encapsulation; the link layer header is a 4-byte field, in network byte order, containing a PF_ value from OpenBSD's socket.h for thenetwork-layer protocol of the packet.Note that, if a ``savefile'' is being read, those PF_ values are not necessarily those of the machine reading the capture file.DLT_LINUX_SLLLinux "cooked" capture encapsulation; the link layer header contains, in order:a 2-byte "packet type", in network byte order, which is one of:packet was sent to us by somebody else1packet was broadcast by somebody else2packet was multicast, but not broadcast, by somebody else3packet was sent by somebody else to somebody else4packet was sent by usa 2-byte field, in network byte order, containing a Linux ARPHRD_ value for the linklayer device type;a 2-byte field, in network byte order, containing the length of the link layer addressof the sender of the packet (which could be 0);an 8-byte field containing that number of bytes of the link layer header (if there are more than 8 bytes, only the first 8 are present);a 2-byte field containing an Ethernet protocol type, in network byte order, orcontaining 1 for Novell 802.3 frames without an 802.2 LLC header or 4 forframes beginning with an 802.2 LLC header.DLT_LTALKApple LocalTalk; the packet begins with an AppleTalk LLAP header.DLT_PFLOGOpenBSD pflog; the link layer header contains, in order:a 4-byte PF_ value, in network byte order;a 16-character interface name;a 2-byte rule number, in network byte order;a 2-byte reason code, in network byte order, which is one of:match1bad offsetfragment3short4normalizememorya 2-byte action code, in network byte order, which is one of:passed1dropped2scrubbeda 2-byte direction, in network byte order, which is one of:incoming or outgoing1incoming2outgoingDLT_PRISM_HEADERPrism monitor mode information followed by an 802.11 header.DLT_IP_OVER_FCRFC 2625 IP-over-Fibre Channel, with the link-layer header being the Network_Header as described in that RFC.DLT_SUNATMSunATM devices; the link layer header contains, in order:a 1-byte flag field, containing a direction flag in the uppermost bit, which is set forpackets transmitted by the machine and clear for packets received by themachine, and a 4-byte traffic type in the low-order 4 bits, which is one of:raw trafficLANE traffic2LLC-encapsulated traffic3MARS traffic4IFMP traffic5ILMI traffic6Q.2931 traffica 1-byte VPI value;a 2-byte VCI field, in network byte order.DLT_IEEE802_11_RADIOlink-layer information followed by an 802.11 header - see /~pizza/software/capturefrm.txt for a description ofthe link-layer information.DLT_ARCNET_LINUXARCNET, with no exception frames, reassembled packets rather than raw frames, and an extra 16-bit offset field between the destination host and type bytes.DLT_LINUX_IRDALinux-IrDA packets, with a DLT_LINUX_SLL header followed by the IrLAP header.int pcap_list_datalinks(pcap_t *p, int **dlt_buf); [INDEX]pcap_list_datalinks()is used to get a list of the supported data link types of the interface associated with the pcap descriptor.pcap_list_datalinks()allocates an array to hold the list and sets*dlt_buf. The caller is responsible for freeing the array.-1is returned on failure; otherwise, the number of data link types in the array is returned.int pcap_set_datalink(pcap_t *p, int dlt); [INDEX]pcap_set_datalink()is used to set the current data link type of the pcap descriptor to the type specified by dlt.-1is returned on failure.int pcap_datalink_name_to_val(const char *name); [INDEX]pcap_datalink_name_to_val()translates a data link type name, which is a DLT_name with the DLT_removed, to the corresponding data link type value. The translation is case-insensitive.-1is returned on failure.const char *pcap_datalink_val_to_name(int dlt); [INDEX]pcap_datalink_val_to_name()translates a data link type value to the corresponding data link type name. NULL is returned on failure.const char *pcap_datalink_val_to_description(int dlt); [INDEX]pcap_datalink_val_to_description()translates a data link type value to a short description of that data link type. NULL is returned on failure.int pcap_snapshot(pcap_t *p) [INDEX]pcap_snapshot()returns the snapshot length specified when pcap_open_live()was called.int pcap_is_swapped(pcap_t *p) [INDEX]pcap_is_swapped()returns true if the current ``savefile'' uses a different byte order than the current system.int pcap_major_version(pcap_t *p) [INDEX]int pcap_minor_version(pcap_t *p) [INDEX]pcap_major_version()returns the major number of the file format of the savefile;pcap_minor_version() returns the minor number of the file format of the savefile. The version number is stored in the header of the savefile.int pcap_stats(pcap_t *p, struct pcap_stat *ps) [INDEX]pcap_stats()returns 0 and fills in a pcap_stat struct. The values represent packet statistics from the start of the run to the time of the call. If there is an error or the underlying packet capture doesn't support packet statistics, -1 is returned and the error text can be obtained with pcap_perror()or pcap_geterr(). pcap_stats()is supported only on live captures, not on ``savefiles''; no statistics are stored in ``savefiles'', so no statistics are available when reading from a ``savefile''.FILE *pcap_file(pcap_t *p) [INDEX]。
循序渐进学习使用WINPCAP(八)尽管WinPcap从名字上来看表明它的主要目的是捕获数据包,但是它还为原始网络提供了一些其它的功能,其中之一就是用户可以发送数据包,这也就是本节的主要内容。
需要指出的是原来的libpcap并不提供数据包的发送功能,这里所说的功能都是WinPcap的扩展功能,所以并不能够工作在UNIX下。
用pcap_sendpacket来发送一个数据包下面的代码是一个最简单的发送数据的方法。
打开一个适配器后就可以用pcap_sendpacket()来手工发送一个数据包了。
这个函数需要的参数:一个装有要发送数据的缓冲区,要发送的长度,和一个适配器。
注意缓冲区中的数据将不被内核协议处理,只是作为最原始的数据流被发送,所以我门必须填充好正确的协议头以便正确的将数据发送。
#include "pcap.h"int main(int argc, char **argv){pcap_t *fp;char error[PCAP_ERRBUF_SIZE];u_char packet[100];int i=0,inum;pcap_if_t *alldevs,*d;/* 获得网卡的列表*/if (pcap_findalldevs(&alldevs, error) == -1){ fprintf(stderr,"Error in pcap_findalldevs: %s\n", error);exit(1);}/* 打印网卡信息*/for(d=alldevs; d; d=d->next){ printf("%d. %s", ++i, d->name);if (d->description) printf(" (%s)\n", d->description);else printf(" (No description available)\n");}if(i==0){ printf("\nNo interfaces found! Make sure WinPcap is installed.\n");return -1;}printf("Enter the interface number (1-%d):",i);scanf("%d", &inum);//输入要选择打开的网卡号if(inum < 1 || inum > i) //判断号的合法性{ printf("\nInterface number out of range.\n");pcap_freealldevs(alldevs); /* Free the device list */return -1;}/* 找到要选择的网卡结构*/for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);/* 打开选择的网卡*/if((fp = pcap_open_live(d->name, 100, 1, 1000, error) ) == NULL){fprintf(stderr,"\nError opening adapter: %s\n", error);return -1;}/* 假设网络环境为ethernet,我门把目的MAC设为1:1:1:1:1:1*/packet[0]=1; packet[1]=1; packet[2]=1;packet[3]=1; packet[4]=1; packet[5]=1;/* 假设源MAC为2:2:2:2:2:2 */packet[6]=2; packet[7]=2; packet[8]=2;packet[9]=2; packet[10]=2; packet[11]=2;/* 填充发送包的剩余部分*/for(i=12;i<100;i++){ packet[i]=i%256;}/* 发送包*/pcap_sendpacket(fp,packet, 100);return 0;}发送队列:pcap_sendpacket()只是提供一个简单的直接的发送数据的方法,而发送队列提供一个高级的强大的和最优的机制来发送一组数据包,队列实际上是一个装有要发送数据的一个容器,它有一个最大值来表明它所能够容纳的最大比特数。
PCAP Multi Touch Screen Display with Dual OSUser’s ManualManual Version AOE1.0Safety Instructions∙ Please keep the display away from any heat sources such as electricradiators or direct sunlight. Place the display in a stable andwell-ventilated place.∙ Please handle with care so as to not damage the LCD panel.∙ The holes or openings on the display are designed for ventilation. Do notcover or block the ventilation holes or openings with any objects.∙ Remove protective covering from the screen before you use the display.∙ As the display surface is vulnerable to scratches, avoid touching thesurface with sharp pen point.∙ Shut off the power supply before cleaning. Use a soft lint-free clothinstead of a tissue to wipe the screen.∙ You may use a glass cleaner to clean the product as required. However,never spray the cleaner directly onto the display surface.∙ Do not attempt to repair this product yourself! Improperly disassembly ofthe product may invalidate the warranty and lead to possible danger!Quick Start Guide (switching between Windows & Android)Begin by connecting a USB keyboard to your screen using one of the following USB ports:Switching from Windows to Android1 of 8.Open the Start Menu by tapping the Windows button, then tap the Power button,then “Restart”:2 of ing the keyboard start continually pressing the “DELETE” key until you see thefollowing screen:3 of 8.The rest of the steps will use the keyboard only. Please use the navigational keys(←,↑,↓ and →) to move around and the “ENTER” key to make a selection. Navigate to andselect the “Advanced” tab then go to and select “System Component”:4 of 8.Select “OS IMAGE ID” and then select “Android”:5 of 8.Press the “Esc” key to close option.6 of 8.Navigate to and select the “Boot” tab, then select “Boot Option #1” and choose“Android-IA”:7 of 8.Finally to save and exit press the “F10” key and then select “Yes”:8 of 8.When your Touch Screen restarts it will do so in the Android operating system.Switching from Android to Windows1 of 8.From the bottom navigation menu tap the “Restart” icon:2 of ing the keyboard start continually pressing the “DELETE” key until you see thefollowing screen:3 of 8.The rest of the steps will use the keyboard only. Please use the navigational keys(←,↑,↓ and →) to move around and the “ENTER” key to make a selection. Navigate to and select the “Advanced” tab then go to and select “System Component”:4 of 8.Select “OS IMAGE ID”and then select “Windows”:5 of 8.Press the “Esc” key to close option.6 of 8.Navigate to and select the “Boot” tab, then select “Boot Option #1” and choose“Windows Boot Manager”:7 of 8.Finally to save and exit press the “F10” key and then select “Yes”:8 of 8.When your Touch Screen restarts it will do so in the Windows operating system.Quick Start Guide (connecting to an external PC/Media Player) Although the screen has a built in PC you can also connect it to an external source. The touch screen must be connected to the PC in two ways: visually and interactively. The recommended visual connection is via the HDMI Cable meaning that the display acts like a monitor for the PC. The touch function is achieved by linking the PCAP panel on the screen directly to the PC via the USB Cable (included).Figure 1 Screen to PC ConnectionsConnect the screen to the PC via HDMI cable and USB cable (as shown above). Once these connections have been made and the PC powered ON take the power lead and insert it into the screen and connect to mains outlet. The unit will power ON automatically. Before taking any more steps ensure that the screen is sourcing its display from the PC. This is done by first pressing “SOURCE” on your remote and then scrolling down to the d esired input source (HDMI) and select by pressing “PLAY”.Contents:Switching from Windows to Android (2)Switching from Android to Windows (4)1.Introduction (9)1.1Box Contents (9)1.2Product Overview (10)1.3Remote Control (11)1.4Replacing the Remote Control Battery (12)2.Menu Operation (13)2.1Inputs (17)3.Switching between Android and Windows (18)3.1.1Switching from Windows to Android (18)3.1.2Switching from Android to Windows (21)3.2Connecting to an external PC/Media Player (24)4. F.A.Qs and Troubleshooting Guide (26)4.1My Screen is not displaying what is on my PC/external source (26)4.1.1Input Source (26)4.1.2Display/monitor button on PC keyboard (26)4.2My monitor's image is unstable, unfocused or swimming (26)Table of FiguresFigure 1 Screen to PC Connections (6)Figure 2 Product Overview (10)Figure 3 Screen Inputs (17)Figure 5 Screen to PC Connections (24)1. IntroductionCongratulations on your purchase of our product. Please read carefully and follow all instructions in the manual before first use.The product should not be exposed to liquids dripping or splashing and no objects filled with liquids, such as vases, should be placed on the product.For user convenience, a number of operations can be performed through the remote control.Attention:1.Do not change any default setting when it is unnecessary.2.Keep the product far away from water during installation and use.1.1 Box Contents1xPCAP Multi Touch Screen (PC integrated)1xPower Cable1xWi-Fi Aerial1xRemote Control (with AAA batteries)1xUSB Male to Male Cable1xCD (User Manual)IMPORTANT: Please retain your screen’s packaging for the duration of your warranty.1.2 Product OverviewFigure 2 Product Overview1.3 Remote Control1.4 Replacing the Remote Control Battery1. Slide the battery cover off, as shown below.2. Remove the used batteries.4. Insert the two new AAA batteries with their terminals corresponding to the indicators.5. Put the cover back on.2. Menu OperationThe Menu features the following sections: Picture, Sound, Time and Option.Press “MENU” to bring up the menus, press ←→ to select the desired menu and ↑↓ to select thedesired item, press “PLAY” to confirm selection. Press the back button () at any time to go back or exit.OptionUnder this menu are settings like on screen display language, on screen display duration time, and the video wall tiling settings. You can also restore all of the menus default settings and change the standby mode.PictureHere is where you can edit settings such as brightness, contrast, colour temperature and backlight brightness. Any settings that you change can be reset back to default at any time.SoundIn this menu you can adjust all of the sound settings for your monitor such as the sound mode EQ settings or the left/right balance. Any settings that you change can be reset back to default at any time.TimeHere you can set a time and date for your screen as well as scheduling daily on/off times for the built in power timer. You can also adjust at what temperature the internal fans become active.Switching between inputsOne crucial feature that does not appear on the Main Menu is selecting the input source. This is done by first pressing the “SOURCE” button on the remote control and then scrolling down to the desired input source and select by pressing “PLAY”.2.1 InputsC5 (Clover Leaf/Mickey Mouse) Power InputLAN – Local Area Network InputUSB (x2)– Universal Serial Bus (both for internal PC)USB (x1)– Universal Serial Bus (for updating firmware on monitor board)HDMI – High Definition Multimedia Interface Signal Input (for HD Video & Audio signal)VGA – Video Graphics Array Signal Input (for Video signal)3.5mm Audio InputRS232 – Serial communication transmission3.5mm Microphone/Audio OutTOUCH USB – Universal Serial Bus (both for updating internal media player)3.5mm Audio OutFigure 3 Screen Inputs3. Switching between Android and WindowsBegin by connecting a USB keyboard to your screen using one of the following USB ports:3.1.1Switching from Windows to Android1 of 8.Open the Start Menu by tapping the Windows button, then tap the Power button,then “Restart”:2 of ing the keyboard start continually pressing the “DELETE” key until yo u see thefollowing screen:3 of 8.The rest of the steps will use the keyboard only. Please use the navigational keys(←,↑,↓ and →) to move around and the “ENTER” key to make a selection. Navigate to and s elect the “Advanced” tab then go to and select “System Component”:4 of 8.Select “OS IMAGE ID” and then select “Android”:5 of 8.Press the “Esc” key to close option.6 of 8.Navigate to and select the “Boot” tab, then select “Boot Option #1” and choose“Android-IA”:7 of 8.Finally to save and exit press the “F10” key and then select “Yes”:8 of 8.When your Touch Screen restarts it will do so in the Android operating system.3.1.2Switching from Android to Windows1 of 8.From the bottom navigation menu tap the “Restart” icon:2 of ing the keyboard start continually pressing the “DELETE” key until you see thefollowing screen:3 of 8.The rest of the steps will use the keyboard only. Please use the navigational keys(←,↑,↓ and →) to move around and the “ENTER” key to make a selection. Navigate to and select the “Advanced” tab then go to and select “System Component”:4 of 8.Select “OS IMAGE ID” and then select “Windows”:5 of 8.Press the “Esc” key to close option.6 of 8.Navigate to and select the “Boot” tab, then select “Boot Option #1” and choose“Windows Boot Manager”:7 of 8.Finally to save and exit press the “F10” key and then select “Yes”:8 of 8.When your Touch Screen restarts it will do so in the Windows operating system.3.2 Connecting to an external PC/Media PlayerAlthough the screen has a built in PC you can also connect it to an external source. The touch screen must be connected to the PC in two ways: visually and interactively. The recommended visual connection is via the HDMI Cable meaning that the display acts like a monitor for the PC. The touch function is achieved by linking the touch sensors in the screen to the PC via the USB Cable (included).Figure 4 Screen to PC ConnectionsConnect the screen to the PC via HDMI cable and USB cables (as shown above). Once these connections have been made and the PC powered ON take the power lead and insert it into the screen and connect to mains outlet. The unit will power ON automatically. Before taking any more steps ensure that the screen is sourcing its display from the PC. This is done by first pressing “SOURCE” on your remote and then scrolling down to the desired input source (HDMI) and select by pressing “PLAY”.IMPORTANT: If the Touch Screen is the only monitor connected to your PC NO NOT take the following step. Only proceed with the following if you are using a laptop or another monitor is connected to your PC.Access the display options from your Control Panel or right-click on your Desktop and choose“Properties” (then “Settings”) or “Screen resolution”. You should now click “Detect” to all ow the PC to discover the Video Monitor then “Identify” to establish which display is the Video Monitor.Select the display that corresponds with the Video Monitor display then check the box “Make this my main display” or “Use this devise as the primary monitor”. This will make the Video Monitor display your main monitor.4. F.A.Qs and Troubleshooting Guide4.1 My Screen is not displaying what is on my PC/external source4.1.1Input SourceYour screen may be sourcing its display from another input. First ensure that your screen is connected to your PC (or other video source) via one of the inputs. Next, press “SOURCE” and then navigate to the input source that corresponds with the one you are using and select by pressing “PLAY”.4.1.2Display/monitor button on PC keyboardIf you are souring your video signal from a PC your keyboard may have a display/monitor button on it, especially if you are using a laptop. If your Video Monitor does not display the content of the PC try hitting this button before contacting your supplier.4.2 My monitor's image is unstable, unfocused or swimmingFirstly check that the video signal cable should is firmly connected to the monitor and the PC. Next, check the monitor and your display card with respect to compatibility and recommended signal timings.If your text is blurred, reformat the video mode to “non-interlaced” and use 60Hz refresh rate.。
让我们从看看这篇文章写给谁开始。
显而易见的,需要一些C语言基础知识,除非你只想了解基本的理论。
你不必是一个编码专家,因为这个领域只有经验丰富的程序员涉足,而我将尽可能详细的描述这些概念。
另外,考虑到这是有关一个包嗅探器的,所以对网络基础知识的理解是有帮助的。
所有在此出现的代码示例都已在FreeBSD 4.3平台上测试通过。
开始:pcap应用程序的格式我们所要理解的第一件事情是一个基于pcap的嗅探器程序的总体布局。
流程如下:1.我们从决定用哪一个接口进行嗅探开始。
在Linux中,这可能是eth0,而在BSD系统中则可能是xl1等等。
我们也可以用一个字符串来定义这个设备,或者采用pcap提供的接口名来工作。
2.初始化pcap。
在这里我们要告诉pcap对什么设备进行嗅探。
假如愿意的话,我们还可以嗅探多个设备。
怎样区分它们呢?使用文件句柄。
就像打开一个文件进行读写一样,必须命名我们的嗅探“会话”,以此使它们各自区别开来。
3.如果我们只想嗅探特定的传输(如TCP/IP包,发往端口23的包等等),我们必须创建一个规则集合,编译并且使用它。
这个过程分为三个相互紧密关联的阶段。
规则集合被置于一个字符串内,并且被转换成能被pcap读的格式(因此编译它)。
编译实际上就是在我们的程序里调用一个不被外部程序使用的函数。
接下来我们要告诉pcap使用它来过滤出我们想要的那一个会话。
4.最后,我们告诉pcap进入它的主体执行循环。
在这个阶段内pcap一直工作到它接收了所有我们想要的包为止。
每当它收到一个包就调用另一个已经定义好的函数,这个函数可以做我们想要的任何工作,它可以剖析所部获的包并给用户打印出结果,它可以将结果保存为一个文件,或者什么也不作。
5.在嗅探到所需的数据后,我们要关闭会话并结束。
这是实际上一个很简单的过程。
一共五个步骤,其中一个(第3个)是可选的。
我们为什么不看一看是怎样实现每一个步骤呢?设置设备这是很简单的。
有两种方法设置想要嗅探的设备。
第一种,我们可以简单的让用户告诉我们。
考察下面的程序:#include <stdio.h>#include <pcap.h>int main(int argc, char *argv[]){char *dev = argv[1];printf("Device: %s", dev);return(0);}用户通过传递给程序的第一个参数来指定设备。
字符串“dev”以pcap能“理解”的格式保存了我们要嗅探的接口的名字(当然,用户必须给了我们一个真正存在的接口)。
另一种也是同样的简单。
来看这段程序:#include <stdio.h>#include <pcap.h>int main(){char *dev, errbuf[PCAP_ERRBUF_SIZE];dev = pcap_lookupdev(errbuf);printf("Device: %s", dev);return(0);}在这个例子里,pcap就自己设置设备。
“但是,等一下,Tim”,你会说,“字符串errbuf 是做什么的?”大多数的pcap命令允许我们向它们传递字符串作为参数。
这个字符串的目的是什么呢?如果命令失败,它将传给这个字符串关于错误的描述。
这样,如果pcap_lookupdev()失败,它将在errbuf存储错误信息。
很好,是不是?这就是我们怎样去设置设备。
打开设备进行嗅探创建一个嗅探会话的任务真的非常简单。
为此,我们使用pcap_open_live()函数。
此函数的原型(根据pcap的手册页)如下:pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)其第一个参数是我们在上一节中指定的设备,snaplen是整型的,它定义了将被pcap捕获的最大字节数。
当promisc设为true时将置指定接口为混杂模式(然而,当它置为false 时接口仍处于混杂模式的特殊情况也是有可能的)。
to_ms是读取时的超时值,单位是毫秒(如果为0则一直嗅探直到错误发生,为-1则不确定)。
最后,ebuf是一个我们可以存入任何错误信息的字符串(就像上面的errbuf)。
此函数返回其会话句柄。
举个例子,考察以下代码片断:#include <pcap.h>...pcap_t *handle;handle = pcap_open_live(somedev, BUFSIZ, 1, 0, errbuf);这个代码片断打开字符串somedev的设备,告诉它读取被BUFSIZ指定的字节数(BUFSIZ在pcap.h里定义)。
我们告诉它将设备置为混杂模式,一直嗅探到错误发生,如果有了错误,把它存放在字符串errbuf中。
混杂模式与非混杂模式的区别:这两种方式区别很大。
一般来说,非混杂模式的嗅探器中,主机仅嗅探那些跟它直接有关的通信,如发向它的,从它发出的,或经它路由的等都会被嗅探器捕获。
而在混杂模式中则嗅探传输线路上的所有通信。
在非交换式网络中,这将是整个网络的通信。
这样做最明显的优点就是使更多的包被嗅探到,它们因你嗅探网络的原因或者对你有帮助,或者没有。
但是,混杂模式是可被探测到的。
一个主机可以通过高强度的测试判定另一台主机是否正在进行混杂模式的嗅探。
其次,它仅在非交换式的网络环境中有效工作(如集线器,或者交换中的ARP层面)。
再次,在高负荷的网络中,主机的系统资源将消耗的非常严重。
过滤通信通常,我们的嗅探器仅对某特定的通信感兴趣。
例如,有时我们想嗅探到端口23(telnet)的包以获得密码;或者我们想截获一个正通过端口21 (FTP)传送的文件;可能我们仅想要得到DNS的通信(端口53,UDP)。
无论哪种情况,我们都很少盲目的嗅探整个网络的通信。
下面讨论pcap_compile()与pcap_setfilter()。
这个过程非常简单。
当我们已经调用了pcap_open_live()从而建立了一个嗅探会话之后就可以应用我们自己的过滤器了。
为什么要用我们自己的过滤器呢?有两个原因。
第一,pcap 的过滤器太强大了,因为它直接使用BPF过滤器,我们通过使用BPF驱动直接过滤跳过了很多的关节。
第二,这样做要容易的多。
在使用我们自己的过滤器前必须编译它。
过滤表达式被保存在一个字符串中(字符数组)。
其句法在tcpdump的手册页中被证明非常好。
我建议你亲自阅读它。
但是我们将使用简单的测试表达式,这样你可能很容易理解我的例子。
我们调用pcap_compile()来编译它,其原型是这样定义的:int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask)第一个参数是会话句柄(pcap_t *handle在前一节的示例中)。
接下来的是我们存储被编译的过滤器版本的地址的引用。
再接下来的则是表达式本身,存储在规定的字符串格式里。
再下边是一个定义表达式是否被优化的整形量(0为false,1为true,标准规定)。
最后,我们必须指定应用此过滤器的网络掩码。
函数返回-1为失败,其他的任何值都表明是成功的。
表达式被编译之后就可以使用了。
现在进入pcap_setfilter()。
仿照我们介绍pcap的格式,先来看一看pcap_setfilter()的原型:int pcap_setfilter(pcap_t *p, struct bpf_program *fp)这非常直观,第一个参数是会话句柄,第二个参数是被编译表达式版本的引用(可推测出它与pcap_compile()的第二个参数相同)。
下面的代码示例可能能使你更好的理解:#include <pcap.h>pcap_t *handle; /* 会话的句柄*/char dev[] = "rl0"; /* 执行嗅探的设备*/char errbuf[PCAP_ERRBUF_SIZE]; /* 存储错误信息的字符串*/struct bpf_program filter; /*已经编译好的过滤表达式*/char filter_app[] = "port 23"; /* 过滤表达式*/bpf_u_int32 mask; /* 执行嗅探的设备的网络掩码*/bpf_u_int32 net; /* 执行嗅探的设备的IP地址*/pcap_lookupnet(dev, &net, &mask, errbuf);handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);pcap_compile(handle, &filter, filter_app, 0, net);pcap_setfilter(handle, &filter);这个程序使嗅探器嗅探经由端口23的所有通信,使用混杂模式,设备是rl0。
你可能注意到前面的示例包含一个我们还没提到的函数:pcap_lookupnet(),向这个函数提供设备接口名,它将返回其IP和网络掩码,这是很基本的,因为我们需要知道网络掩码以便应用过滤器。
此函数在此文最后的miscellaneous一节里还有描述。
据我的经验,这个过滤器在所有的操作系统下都不会工作。
在我的测试环境里,我发现OpenBSD 2.9默认内核支持这种过滤器,但FreeBSD 4.3默认内核则不支持。
你的情况可能会有变化。
实际的嗅探到此为止,我们已经学习了如何定义一个设备,让它准备嗅探,还有应用过滤器使我们嗅谈到什么或者不嗅探到什么。
现在到了真正去捕获一些数据包的时候了。
有两种手段捕获包。
我们可以一次只捕获一个包,也可以进入一个循环,等捕获到多个包再进行处理。
我们将先看看怎样去捕获单个包。
pcap_next()的原型及其简单:u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)第一个参数是会话句柄,第二个参数是指向一个包括了当前数据包总体信息(被捕获时的时间,包的长度,其被指定的部分长度)的结构体的指针(在这里只有一个片断,只作为一个示例)。
Pcap_next()返回一个u_char指针给被这个结构体描述的包。
我们将稍后讨论这种实际读取包本身的手段。
这里有一个演示怎样使用pcap_next()来嗅探一个包的例子:#include <pcap.h>#include <stdio.h>int main(){pcap_t *handle; /* 会话句柄*/char *dev; /* 执行嗅探的设备*/char errbuf[PCAP_ERRBUF_SIZE]; /* 存储错误信息的字符串*/struct bpf_program filter; /* 已经编译好的过滤器*/char filter_app[] = "port 23"; /* 过滤表达式*/bpf_u_int32 mask; /* 所在网络的掩码*/bpf_u_int32 net; /* 主机的IP地址*/struct pcap_pkthdr header; /* 由pcap.h定义*/const u_char *packet; /* 实际的包*//* Define the device */dev = pcap_lookupdev(errbuf);/* 探查设备属性*/pcap_lookupnet(dev, &net, &mask, errbuf);/* 以混杂模式打开会话*/handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);/* 编译并应用过滤器*/pcap_compile(handle, &filter, filter_app, 0, net);pcap_setfilter(handle, &filter);/* 截获一个包*/packet = pcap_next(handle, &header);/* 打印它的长度*/printf("Jacked a packet with length of [%d]", header.len);/* 关闭会话*/pcap_close(handle);return(0);}这个程序嗅探被pcap_lookupdev()返回的设备并将它置为混杂模式。