最近对网络编程来了兴趣,开始研究libpcap把自己的一些学习历程写下来,绝对是由浅入深希望对大家有帮助
本文版权所有:doggy(chaujy@x263.net) 欢迎非盈利性转载
任何其他形式的使用请与作者联系
1.入门使用篇
本篇讲述如何抓包
最简单的libpcap抓包程序只要有以下几句就可以了
char ebuf[PCAP_ERRBUF_SIZE];
pcap_t *pd = pcap_open_live("eth0", 68, 0, 1000, ebuf);
建立libpcap捕捉句柄,若出错,ebuf返回错误字串.ebuf可以为NULL(以后同)
struct bpf_program fcode;
pcap_compile(pd, &fcode, NULL, 1, 0);
添写过滤规则串fcode,可以为空(即第三个参数,格式在后面讲到)
pcap_setfilter(pd, &fcode);
给 pd 设置上过滤规则
pcap_loop(pd, 10, eth_printer, NULL);
主循环,开始抓包,共抓10个(由第二个参数指定),抓到包后就进入函数 eth_printer
pcap_close(pd);
结束
这个就是最简单的程序了,其中还有个不明,
在pcap_loop参数 eth_printer的类型是pcap_handler,pcap_handler定义如下:
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
const u_char *);
当然要包含
#include "pcap.h"
编译要加上 -lpcap
至于怎么得到libpcap,还有安装,我就不费话了
本文版权所有:doggy(chaujy@x263.net) 欢迎转载
2.使用进阶篇
刚才我们对程序的要求是能编译通过,能运行成功,现在我们让这个程序实用点吧
2.1 其它几个函数介绍
这几个函数的特点是简单但无关紧要
现在我们隆重退出
char * pcap_lookupdev ( char * errbuf );
这个函数就是查找本机上的网络接口设备,我机器上就返回"eth0",在pcap_open_live之前用,没什么意思吧,反正我是不爱用它
int pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *);
第一个参数就是pcap_lookupdev返回的接口名,二三参数都是32位无符号数,分别是IP网段和掩码,最后那个参数还是ebuf
int pcap_datalink(pcap_t *);
它返回你的网络类型,如 DLT_EN10MB 就是10M以太网,让人ft的是这些常量定义不在pcap.h中,在哪?自己找找吧;-)
int pcap_snapshot(pcap_t *);
返回最长抓多少字节,就是我们在pcap_open_live中第二个参数设置的
int pcap_stats(pcap_t *, struct pcap_stat *);
计数,共抓了多少过滤掉了多少,看看struct pcap_stat的定义就明白了
struct pcap_stat {
u_int ps_recv; /* number of packets received */
u_int ps_drop; /* number of packets dropped */
u_int ps_ifdrop; /* drops by interface XXX not yet supported */
};
int pcap_major_version(pcap_t *);
int pcap_minor_version(pcap_t *);
版本号,你有用么?
我的eth_printer如下
void eth_printer(u_char * user, const struct pcap_pkthdr * h, const u_char * p)
{
printf("I get one packet! ");
}
简单吧 :*)
2.2 现在的程序(C++)
文件名p.cxx
#ifdef __cplusplus
extern “C” {
#endif
#include
#ifdef __cplusplus
}
#endif
void printer(u_char * user, const struct pcap_pkthdr * h, const u_char * p)
{
printf(”I get one packet! “);
/* 哈哈,我都想喝一杯庆祝一下了! */
}
#define DEFAULT_SNAPLEN 68
/* 别问我为什么是68,我从tcpdump看来的 */
int main()
{
char ebuf[PCAP_ERRBUF_SIZE];
char *device = pcap_lookupdev(ebuf);
bpf_u_int32 localnet, netmask;
pcap_lookupnet(device, &localnet, &netmask, ebuf);
printf(”%u.%u.%u.%u”, localnet&0xff, localnet>>8&0xff,
localnet>>16&0xff, localnet>>24&0xff);
printf(”:%d.%d.%d.%d “, netmask&0xff, netmask>>8&0xff,
netmask>>16&0xff, netmask>>24&0xff);
struct pcap_t *pd = pcap_open_live(device, DEFAULT_SNAPLEN, 0, 1000, ebuf);
if(pcap_datalink(pd) == DLT_EN10MB)
printf(”10Mb以太网 “);
struct bpf_program fcode;
pcap_compile(pd, &fcode, NULL, 1, 0);
pcap_setfilter(pd, &fcode);
pcap_loop(pd, 10, printer, NULL);
struct pcap_stat stat;
pcap_stats(pd, &stat);
printf(”recv %d, drop %d. “, stat.ps_recv, stat.ps_drop);
pcap_close(pd);
}
#gcc p.cxx -lpcap
#./a.out
166.111.168.0:255.255.252.0
10Mb以太网
I get one packet!
I get one packet!
I get one packet!
I get one packet!
I get one packet!
I get one packet!
I get one packet!
I get one packet!
I get one packet!
I get one packet!
recv 10, drop 0.
#
重要提示: libpcap 程序需要root权限
费了半天劲显示网段和掩码,抓了10个包,值得吗?
2.3 出错处理
象其它库一样,libpcap 也有自己的错误处理机制,基本上每个函数都有返回值,出错时返回值<0,另外有如下函数
void pcap_perror(pcap_t *, char *);
char *pcap_strerror(int);
char *pcap_geterr(pcap_t *);
前两个和 perror() strerror() 用法相同,最后一个也很简单,在 pcap_t 中有一个成员存了错误字串
struct pcap {
...
char errbuf[PCAP_ERRBUF_SIZE];
};
所以......
于是我们在刚才的程序中加上错误处理
先加一个函数
#include
int err_quit(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
exit(-1);
}
之后处理每个函数的异常,在成功建立捕捉句柄pcap_t *pd前,使用ebuf参数
char *device = pcap_lookupdev(ebuf);
if(device == NULL)
err_quit("%s", ebuf);
有了句柄pd后
if(pcap_compile(pd, &fcode, NULL, 1, 0) < 0)
err_quit("%s", pcap_geterr(pd));
注意不是每个函数都是出错返回<0
pcap_datalink(pd)和pcap_snapshot(pd)等可不要这么处理
2.4 参数初步研究
前面使用各函数时,并没有具体说明每个函数的意义,现在来探讨一下
pcap_t * pcap_open_live(char *device, int snaplen, int promisc,
int to_ms, char *ebuf)
device指定设备,snaplen指定最长抓多少字节,ebuf出错信息,前面都说过
promisc指出是否设置为混杂模式(不懂?我也不懂,整个网都听还有什么安全性可言)
to_ms设置超时时间,单位milliseconds
int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
cnt为要抓的包数,pcap_loop在正常时抓cnt个包后返回,异常时返回值<0
user是要传入callback()的数据,例如我们把上面的程序修改几行
file://pcap_loop(pd, 10, printer, NULL);
pcap_loop(pd, 10, printer, (u_char*)pd);
再在printer()内加
pcap_stat stat;
pcap_stats((pcap_t*)user, &stat);
printf("recv %d, drop %d. ", stat.ps_recv, stat.ps_drop);
再编译运行后输出为
166.111.168.0:255.255.252.0
10Mb以太网
recv 1, drop 0.
recv 2, drop 0.
recv 3, drop 0.
recv 4, drop 0.
recv 5, drop 0.
recv 6, drop 0.
recv 7, drop 0.
recv 8, drop 0.
recv 9, drop 0.
recv 10, drop 0.
recv 10, drop 0.
int pcap_compile(pcap_t *p, struct bpf_program *program,
char *buf, int optimize, bpf_u_int32 mask)
该函数用于解析过滤规则串buf,填写bpf_program结构.
optimize为1表示对过滤规则进行优化处理
netmask指定子网掩码
buf的格式比较复杂
int pcap_setfilter(pcap_t *handle, struct bpf_program *filter)
把pcap_compile()构造的filter设置到handle上
今天到这里吧,改天有时间再继续
大家早上好,我晚安 :,)
分享到:
相关推荐
java web 学习简单实例
在"springmvc4简单例子"中,我们通常会涉及到以下几个关键知识点: 1. **配置**:首先,你需要配置Spring MVC的DispatcherServlet,这是Spring MVC应用的入口点。在`web.xml`中,你会看到类似下面的配置,用于初始...
这个“html5简单实例”着重展示了HTML5与jQuery Mobile的结合应用,这是一个流行的前端框架,用于创建响应式和触屏友好的移动Web应用程序。 HTML5的新特性包括: 1. **离线存储**:通过`localStorage`和`...
在这个简单的MFC例子中,你可能会看到如何在资源编辑器中创建对话框,如何在代码中实例化和初始化控件,以及如何处理用户交互事件。通过学习这个例子,你可以对MFC的基本概念和控件使用有一个初步的了解,为进一步...
总结,"struts2简单实例"展示了如何使用Struts2框架构建一个简单的学生信息查询功能,涵盖了配置文件、Action实现、数据传输以及视图展示等多个方面,是学习和理解Struts2工作原理的好例子。通过这个实例,开发者...
html5 简单实例源代码
总的来说,这个“ARM学习简单例子”旨在帮助初学者熟悉ARM架构下的编程,特别是通过控制LED来实践GPIO的操作。通过这个实例,你可以学习到基本的ARM汇编语言、C语言编程、GPIO接口以及嵌入式系统的开发流程。随着...
这个“C# 委托简单实例”是理解委托概念的基础教程,特别适合初学者入门。该实例的核心是通过委托来实现温度监控,包括显示温度和触发警告的功能。 首先,我们需要定义一个委托类型,它代表一个接受特定参数并返回...
在这个名为“mfc的一个简单例子”的项目中,我们可以预期它会展示如何在Visual C++环境下使用MFC创建一个基本的图形用户界面(GUI)。MFC将窗口、控件、菜单、对话框等元素抽象为类,程序员可以通过继承和实例化这些...
本文主要讲解了u-boot中的lds文件实例和简单实例分析,涵盖了链接脚本的基础知识、基本概念、脚本格式、简单例子、简单脚本命令、对符号的赋值、SECTIONS命令、MEMORY命令、PHDRS命令、VERSION命令、脚本内的表达式...
Ajax最简单例子,一个例子让你明白Ajax原理,XMLHttpRequest原理 var http_request = false; function createRequest(url) { http_request = false; if (window.XMLHttpRequest) { // Mozilla浏览器 ...
【标题】:“Webservice接口开发简单例子” 在IT行业中,Web Service是一种基于互联网的、用于应用程序之间进行交互的标准化通信方式。本示例将探讨如何开发一个简单的Web Service接口,以便不同系统间能够共享数据...
在"MVVM最简单实例程序"中,开发者可能创建了一个简单的WPF应用,演示了如何使用MVVM模式。这个实例可能包括一个简单的View(如一个窗口,里面有几个按钮和文本框),一个ViewModel(处理按钮点击事件和更新UI),...
这是关于delphi应用的简单实例(包含多个例子)。
总结起来,实现"android 仿京东商品三级分类简单实例"需要关注以下几个关键点:UI设计(包括RecyclerView的使用),数据结构设计(树形结构),适配器的编写,点击事件处理以及在不同级别间切换的逻辑。虽然这个实例...
本教程将通过一系列简单实例深入浅出地介绍Java的基础知识。 首先,我们要了解Java的基本结构。一个简单的Java程序通常由类(Class)组成,每个类都包含变量(Attributes)和方法(Methods)。在Java中,程序的执行...
这个“java实现的opc ua客户端/服务端的简单例子”是一个很好的起点,对于初学者来说,可以帮助理解 OPC UA 的核心概念和Java实现。 首先,OPC UA 包含了客户端和服务端两部分,客户端用于请求和访问服务器上的数据...
标题 "mybatis简单例子" 涉及到的是MyBatis这一流行的数据持久层框架的实践应用。MyBatis是一个轻量级的Java框架,它允许开发者将SQL语句直接映射到Java方法,简化了数据库操作。在这个简单的例子中,我们将探讨如何...
C++编写的共享库,用gcc编译连接,分别生成.so和.a,C编写的main,用gcc编译,连接.so和.a调用的简单例子
标题"threejs简单例子,threejs中文实例,JavaScript"表明我们将通过一个简单的示例来学习Three.js的基础应用,并且这个示例是针对中文用户编写的。 首先,Three.js的核心概念包括场景(Scene)、相机(Camera)和...