为了开发需要,我决定使用最新libpcap源码包安装。在Unix环境下安装libpcap库,需要
c编译器,flex,bison等,安装Ubuntu系统时,没有这些包。安装flex需要m4编译环境,否则会提示“GNU M4 is required”错误。

1.安装系统依赖包
sudo apt-get install gcc libc6-dev
sudo apt-get install m4 
sudo apt-get install flex bison

2.下载libpcap源码并安装
从官网http://www.tcpdump.org/下载最新的libpcap版本
cd /usr/local/src
wget http://www.tcpdump.org/release/libpcap-1.5.3.tar.gz
tar zxvf libpcap-1.5.3.tar.gz
cd libpcap-1.5.3
./configure
make
sudo make install

3.安装开发需要用到的依赖库
sudo apt-get install libpcap-dev

4.测试libpcap的小程序,命名为pcap_demo.c,以检验环境是否配置正确
#include <pcap.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
pcap_t *handle; /* Session handle */
char *dev; /* The device to sniff on */
char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
struct bpf_program fp; /* The compiled filter */
char filter_exp[] = "port 80"; /* The filter expression */
bpf_u_int32 mask; /* Our netmask */
bpf_u_int32 net; /* Our IP */
struct pcap_pkthdr header; /* The header that pcap gives us */
const u_char *packet; /* The actual packet */

/* Define the device */
dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
return(2);
}
/* Find the properties for the device */
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf);
net = 0;
mask = 0;
}
/* Open the session in promiscuous mode */
handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
return(2);
}
/* Compile and apply the filter */
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
return(2);
}
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
return(2);
}
/* Grab a packet */
packet = pcap_next(handle, &header);
/* Print its length */
printf("Jacked a packet with length of [%d]\n", header.len);
/* And close the session */
pcap_close(handle);
return(0);
}
开始编译:
    gcc -g pcap_demo.c -o pcap_demo -lpcap  
开始执行
    ./pcap_demo

5.注意的问题
5.1.注意使用root用户来执行,或者对普通用户使用sudo来提升权限
    sudo pcap_demo
5.2.对一些PCAP API函数要有全面地理解,并时刻更新文档,比如pcap_loop这个函数,下面是官网的man page地址
http://www.tcpdump.org/manpages/pcap.3pcap.html
5.3,对一些函数的理解:
    pcap_loop和pcap_dispatch的区别,前者不会超时返回,而是会尽量去读取更多的包,直至发生一个错误才返回。正常返回的值是0,否则就是负值。我目前需要连续不断地抓包,所以应该使用pcap_loop。pcap_dispatch内部会调用pcap_loop。pcap_loop中的第四个参数在某些应用中很有用,但是在通常情况下被设为NULL。这种定义很有用,比如假如你想给pcap_loop的回调函数再额外传递一些参数,你可以使用u_char类型的指针(字符串),传人到回调函数中再做具体地处理。pcap_dispatch只会处理它收到的第一批包。
从pcap_loop返回后,我们应该显式调用pcap_close来关闭pcap以便释放资源。为了表示连续不间断的抓包,在pcap_loop中要尽量使用-1而不是0.关于其中回调函数的说明,里面有3个参数。第一个参数user是pcap_loop中最后一个参数,它表示某个不太重要的信息,可以忽略,第二个参数是包头信息,含有包的时间戳和长度,第三个参数是包的数据,从链路层头开始,它在该回调函数中并不会被释放,但是当该回调返回时不包装这些数据再合法,所以要再次使用它们,请事先复制出来。

下面再深入研究一下pcap_loop这个回调函数的定义:
首先注意函数的返回值是void类型,这完全符合逻辑,因为pcap_loop根本不知道如何处理回调函数的返回值,就是给他传出返回值也没有意义。然后就是回调函数的第一个参数对应pcap_loop中的最后一个参数,不管你给pcap_loop的最后一个参数传递什么值,当回调函数被调用时,它都会作为第一个参数传递给回调函数,第二个参数是pcap头,它包含一些信息:抓包时间,包多大,等等,这个结构在pcap.h中定义,如下
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length this packet (off wire) */
};

抓包方式有两种,一种是每次抓一个包,另一种是循环抓包,分为循环抓有限个数的包,或者是无限循环抓包。其中每次抓一个包使用pcap_next函数。pcap_next()表示只抓取一个数据包,它的第一个参数是session handle,第二个参数是包头,返回值是包数据。函数原型如下
u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
另一种循环抓包的方法,就是使用pcap_loop和回调函数,代码样例参见我整理出的两个例子。

5.4.网卡设备的设置有两种方法,第一种方法是用户直接指定网卡名称(必须要真实可用),从命令行参数传递进去,比如
#include <stdio.h>
#include <pcap.h>

int main(int argc, char *argv[])
{
char *dev = argv[1];

printf("Device: %s\n", dev);
return(0);
}
另一种方法,是让pcap自己去探测网卡设备,如果出错,会给出出错信息,但是这种方法很多情况下不靠谱,对此的改进是,让pcap探测出所有的网卡设备,让用户区选择使用那个网络设备抓包,参见下面的代码
#include <stdio.h>
#include <pcap.h>

int main(int argc, char *argv[])
{
char *dev, errbuf[PCAP_ERRBUF_SIZE];

dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
return(2);
}
printf("Device: %s\n", dev);
return(0);
}

5.5.对我们抓到的数据包,它的结构,大体分为Ethernet header,IP header,TCP header等等,分别对应14,20,20个字节,IP header至少20个字节,TCP头也至少20个字节。
data=recv_data[42:]这样做的原因是,recv_data 抓到的都是raw packet, tcp/ip是分了5层,一个udp包,会带有 14Bytes的Ethenet_II Frame的头,然后是20个字节的ip包头,而udp包头有8个字节,所以偏移量42之后的才是udp的实际内容
tcp包的包头大小为20Bytes,所以其实际内容在偏移量54之后

5.6.对数据包的解包和组包,需要用到Ethernet header,IP header,TCP header,UDP header等常用数据结构的定义,我们并不需要重新定义这些头,直接引用相关的头文件定义就可以了。
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>

5.6.对我们目前的程序,通常需要从命令行传人如下参数信息:
  wlan0        待抓包的网卡名称
  tcp port 80  过滤表达式
  10000 or -1  抓包模式,是抓指定个数的包(这里是10000个包),还是无限抓包下去
当然,对这些参数,你也可以写死在程序里。

参考文献
[1].http://www.tcpdump.org/pcap.html

在Ubuntu 14.04 64位上使用libpcap进行抓包和解包相关推荐

  1. Go在Ubuntu 14.04 64位上的安装过程

    1. 从 https://golang.org/dl/  或  https://studygolang.com/dl 下载最新的发布版本go1.10即go1.10.linux-amd64.tar.gz ...

  2. Ubuntu 14.04 64位上安装wps office软件

    废话少说,只给出方法供各位参考!wps for Linux版本已经有两三年没有大的动作,当然其他平台,比如windows,Android,ios上的wps效果还是很赞的说. 下面是我成功安装的步骤: ...

  3. Ubuntu 14.04 64位上安装Valgrind 3.13.0 操作步骤

    关于Valgrind的介绍和使用可以参考: http://blog.csdn.net/fengbingchun/article/details/50196189 在Ubuntu 14.04上可以通过以 ...

  4. Ubuntu 14.04 64位上安装Adobe reader 9.5.5

    首先说明下面的方法本非完美的方案,但是我试验了下,确实可行. 1.从Adobe官网下载最新版的Adobe Reader 9.5.5的deb包,在下面的ftp位置: 2.安装相关依赖库,主要是ia-32 ...

  5. Ubuntu 14.04 64位上配置JDK操作步骤

    1. 从  http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html  下载jdk-8u1 ...

  6. Ubuntu 14.04 64位机上配置Android Studio操作步骤

    Android Studio是一个为Android平台开发程序的集成开发环境.2013年5月16日在Google I/O上发布,可供开发者免费使用.Android Studio基于JetBrains ...

  7. Ubuntu 14.04 64位安装32位兼容包

    问题描述 我的操作系统是64bit版的Ubuntu 14.04,很多32bit的软件无法安装使用,因此希望通过安装32位兼容包解决. 安装过程 在Ubuntu 13.10之前,可以通过安装 ia32- ...

  8. linux运行qsql,c – QSqlDatabase:未在Ubuntu 15.04 64位上加?...

    在Ubuntu 15.04 64位中,我安装了Qt5.6(在线安装程序),在尝试将我的开发环境从Windows 7迁移到Linux时,我面临以下问题: SqlDatabase: QMYSQL driv ...

  9. linux运行qsql,QSqlDatabase:未在Ubuntu 15.04 64位上加​​载QMYSQL驱动程序

    在Ubuntu 15.04 64位中,我安装了Qt5.6(在线安装程序),并且在尝试将开发环境从Windows 7迁移到Linux时,遇到了以下问题: SqlDatabase: QMYSQL driv ...

最新文章

  1. jTable保存到mysql_怎么把从数据库里的数据输到JTABLE里面
  2. creator找不到编译器 qt_VS2017直接使用QT库创建程序
  3. mongoDB 删除集合后,空间不释放
  4. Dynamics 365 on-premises 安装
  5. UESTC 250 windy数 数位dp
  6. Windows环境下安装redis以及出现的一些未解决的问题
  7. java string范围_java,String
  8. 一种使用pyinstaller时图标问题解决方案
  9. Window Server 2008 R2 文件权限管理
  10. JAVA/JNI的jstring转换为char*
  11. ts转换成mp4,ts转mp4方法
  12. AdaBoost 自适应增强 简单易懂 by hch
  13. matlab求两向量夹角_高考数学解题技巧:专题21 平面向量中最值、范围问题高中数学黄金解题模板...
  14. 网络天才网页中文版_【在线猜谜类网页游戏】网络天才网页版在线玩
  15. metrics.accuracy_score()函数 计算acc
  16. gitlab push 时提示 “Empty Reply From Server”
  17. 亲爱的数据工作者,教你绕开13个雷区的方法
  18. 鼠友题库每日百题(三)
  19. jstack 线程状态详解
  20. java app游戏源代码_跪求游戏java源代码

热门文章

  1. Ubuntu中的minicom
  2. 用C#来开发CAD插件,含源代
  3. 哑谜,回文和暴力之美
  4. html5网页怎么实现内容追加,纯js实现网页内容复制后自动追加自定义内容
  5. 《OpenCV3编程入门》学习笔记7 图像变换(三 )重映射
  6. Java快速创建大量对象_3分钟 快速理解JVM创建对象的步骤!
  7. php 5.4 iis6,WIN2003+IIS6+FastCGI+PHP5.4的安装配置
  8. c++判断奇偶_常用的数据差错控制技术(2) 奇偶校验
  9. 站覆盖范围_你了解无线覆盖范围和穿墙能力吗?别再走进这些误区了
  10. 代码整理工具_程序员软件:程序员有哪些常用又好用的编码小工具?