pcap文件格式是常用的数据报存储格式,包括wireshark在内的主流抓包软件都可以生成这种格式的数据包
下面对这种格式的文件简单分析一下: 
pcap文件的格式为:
  文件头    24字节
  数据报头 + 数据报  数据包头为16字节,后面紧跟数据报
  数据报头 + 数据报  ......
pcap.h里定义了文件头的格式
struct pcap_file_header {
        bpf_u_int32 magic;
        u_short version_major;
        u_short version_minor;
        bpf_int32 thiszone;    
        bpf_u_int32 sigfigs;   
        bpf_u_int32 snaplen;   
        bpf_u_int32 linktype;  
};

Pcap文件头24B各字段说明:

Magic:4B:0x1A 2B 3C 4D:用来标示文件的开始
Major:2B,0×02 00:当前文件主要的版本号
Minor:2B,0×04 00当前文件次要的版本号
ThisZone:4B当地的标准时间;全零
SigFigs:4B时间戳的精度;全零
SnapLen:4B最大的存储长度
LinkType:4B链路类型
常用类型:
0            BSD loopback devices, except for later OpenBSD
1            Ethernet, and Linux loopback devices
6            802.5 Token Ring
7            ARCnet
8            SLIP
9            PPP
10           FDDI
100         LLC/SNAP-encapsulated ATM
101         “raw IP”, with no link
102         BSD/OS SLIP
103         BSD/OS PPP
104         Cisco HDLC
105         802.11
108         later OpenBSD loopback devices (with the AF_value in network byte order)
113         special Linux “cooked” capture
114         LocalTalk

字段说明:
Timestamp:时间戳高位,精确到seconds(值是自从January 1, 1970 00:00:00 GMT以来的秒数来记)
Timestamp:时间戳低位,精确到microseconds (数据包被捕获时候的微秒(microseconds)数,是自ts-sec的偏移量)
Caplen:当前数据区的长度,即抓取到的数据帧长度,由此可以得到下一个数据帧的位置。
Len:离线数据长度:网络中实际数据帧的长度,一般不大于caplen,多数情况下和Caplen数值相等。
(例如,实际上有一个包长度是1500 bytes(Len=1500),但是因为在Global Header的snaplen=1300有限制,所以只能抓取这个包的前1300个字节,这个时候,Caplen = 1300 )
Packet 数据:即 Packet(通常就是链路层的数据帧)具体内容,长度就是Caplen,这个长度的后面,就是当前PCAP文件中存放的下一个Packet数据包,也就 是说:PCAP文件里面并没有规定捕获的Packet数据包之间有什么间隔字符串,下一组数据在文件中的起始位置。我们需要靠第一个Packet包确定。 最后,Packet数据部分的格式其实就是标准的网路协议格式了可以任何网络教材上找得到。
下面是我针对网上相关代码的修改和精炼,主要就是改进了读包方法,每次先读包头,再一次性读取该包数据,并在该包数据内依次解析Ethernet帧,IP帧,TCP帧或是UDP帧。另外改进了异常处理机制,保证退出时文件要关闭,内存要释放。注意运行在64位Linux系统上面;
文件pcap_file_parse.c
//description: parse wireshark pcap file and write it into local file
//platform: Ubuntu 14.04 64bit Desktop version
//compile:  gcc -g pcap_file_parse.c -o pcap_file_parse
//run: ./pcap_file_parse test.pcap
//author: tao_627@aliyun.com, QQ:48019671
//date: 2014-05-24#include <pcap.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#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>
#include "pcap_utils.h" //公共函数存放在这里#define STRSIZE 1024
#define SNAP_LEN 1518       // 以太网帧最大长度
#define SIZE_ETHERNET 14   // 以太网包头长度 mac 6*2, type: 2
#define SIZE_UDP 8         // UDP包头8字节int main(int argc, char **argv){if(argc<=1 || argc>2){printf("Usage: %s <input filename>\n", argv[0]);return 0;}struct pcap_file_header *file_header;struct pcap_pkthdr *ptk_header;struct ether_header *eth_header;struct iphdr *ip_header;struct tcphdr *tcp_header;struct udphdr *udp_header;const char *payload;int size_packet, size_payload, size_ip, size_tcp;FILE *fp, *output;int pkt_offset, i=0;char buf[STRSIZE], capture_time[STRSIZE];u_char *packet = NULL;if((fp=fopen(argv[1], "r")) == NULL){printf("Error: can not open input pcap file\n");exit(0);}if((output=fopen("./output.txt", "w+")) == NULL){printf("Error: can not open the output file\n");exit(0);}file_header = (struct pcap_file_header*)malloc(sizeof(struct pcap_file_header));ptk_header = (struct pcap_pkthdr*)malloc(sizeof(struct pcap_pkthdr));//validate the pcap file formatint read_size = fread(file_header, sizeof(char), 24, fp);if(read_size != 24){printf("cannot read pcacp file header, invalid format\n");goto cleanup;}printf("Pcap file header: %X, %hu, %hu, %u, %u\n",file_header->magic,file_header->version_major,file_header->version_minor,file_header->snaplen,file_header->linktype);//allocate a common packet buffer to usepacket = (u_char*)malloc(file_header->snaplen * sizeof(char));pkt_offset = 24;while(fseek(fp, pkt_offset, SEEK_SET) == 0){i++;memset(buf,0,sizeof(buf));memset(packet,0,sizeof(packet));//read pcap packet headerif(fread(buf, 16, 1, fp) != 1){printf("\nPacket No#%d: cannot read pcap_pkt_header of pcap file\n", i);break;}ptk_header->ts.tv_sec = *(bpf_u_int32*)buf;ptk_header->caplen = *(bpf_u_int32*)(buf+8);ptk_header->len = *(bpf_u_int32*)(buf+12);size_packet = ptk_header->caplen;pkt_offset += 16 + size_packet;strftime(capture_time, sizeof(capture_time), "%Y-%m-%d %T", localtime(&(ptk_header->ts.tv_sec)));printf("capture time: %s, packet len: %u\n", capture_time, size_packet);//read a complete packetif(fread(packet, 1, size_packet, fp) != size_packet){printf("Packet NO.%d: cannot read a whole packet\n", i);break;}eth_header = (struct ether_header*)packet;//read ip frame headerip_header = (struct iphdr *)(packet + SIZE_ETHERNET);size_ip = (ip_header->ihl)*4;/* if (size_ip < 20) {printf("无效的IP头长度: %u bytes\n", size_ip);break;}*/if ( (ip_header->protocol != IPPROTO_TCP)&&(ip_header->protocol!=IPPROTO_UDP) ){ // TCP,UDP,ICMP,IPcontinue;}if(ip_header->protocol==IPPROTO_TCP){/* TCP头 */tcp_header = (struct tcphdr *)(packet + SIZE_ETHERNET + size_ip);size_tcp = (tcp_header->th_off)*4;if (size_tcp < 20) {printf("无效的TCP头长度: %u bytes\n", size_tcp);break;}int sport =  ntohs(tcp_header->th_sport);int dport =  ntohs(tcp_header->th_dport);printf("%s:%d -> ", inet_ntoa(*(struct in_addr*)(&ip_header->saddr)), sport);printf("%s:%d ", inet_ntoa(*(struct in_addr*)(&ip_header->daddr)), dport);//内容payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);//内容长度size_payload = ntohs(ip_header->tot_len) - (size_ip + size_tcp);if (size_payload > 0) {printf("seq:%d ack:%d flag:%d payload:%d bytes\n", ntohs(tcp_header->th_seq), ntohs(tcp_header->th_ack), ntohs(tcp_header->th_flags), size_payload );printf("=====================================TCP=====================================\n");print_payload(payload, size_payload);}}else if(ip_header->protocol==IPPROTO_UDP){udp_header = (struct udphdr *)(packet + SIZE_ETHERNET + size_ip);int sport =  ntohs(udp_header->source);int dport =  ntohs(udp_header->dest);printf("%s:%d -> ", inet_ntoa(*(struct in_addr*)(&ip_header->saddr)), sport);printf("%s:%d ", inet_ntoa(*(struct in_addr*)(&ip_header->daddr)), dport);//内容payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + SIZE_UDP);//内容长度size_payload = ntohs(ip_header->tot_len) - (size_ip + SIZE_UDP);if (size_payload > 0) {printf("payload:%d bytes\n", size_payload );printf("=====================================UDP=====================================\n");print_payload(payload, size_payload);}}}cleanup:if(file_header)free(file_header);if(ptk_header)free(ptk_header);if(packet)free(packet);fclose(fp);fclose(output);return 0;
}

文件pcap_utils.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>/** print data in rows of 16 bytes: offset   hex   ascii** 00000   47 45 54 20 2f 20 48 54  54 50 2f 31 2e 31 0d 0a   GET / HTTP/1.1..*/
void
print_hex_ascii_line(const u_char *payload, int len, int offset)
{int i;int gap;const u_char *ch;/* offset */printf("%05d   ", offset);/* hex */ch = payload;for(i = 0; i < len; i++) {printf("%02X ", *ch);ch++;/* print extra space after 8th byte for visual aid */if (i == 7)printf(" ");}/* print space to handle line less than 8 bytes */if (len < 8)printf(" ");/* fill hex gap with spaces if not full line */if (len < 16) {gap = 16 - len;for (i = 0; i < gap; i++) {printf("   ");}}printf("   ");/* ascii (if printable) */ch = payload;for(i = 0; i < len; i++) {if (isprint(*ch))printf("%c", *ch);elseprintf(".");ch++;}printf("\n");
}/** print packet payload data (avoid printing binary data)*/
void
print_payload(const u_char *payload, int len)
{int len_rem = len;int line_width = 16;           /* number of bytes per line */int line_len;int offset = 0;                 /* zero-based offset counter */const u_char *ch = payload;if (len <= 0)return;/* data fits on one line */if (len <= line_width) {print_hex_ascii_line(ch, len, offset);return;}/* data spans multiple lines */for ( ;; ) {/* compute current line length */line_len = line_width % len_rem;/* print line */print_hex_ascii_line(ch, line_len, offset);/* compute total remaining */len_rem = len_rem - line_len;/* shift pointer to remaining bytes to print */ch = ch + line_len;/* add offset */offset = offset + line_width;/* check if we have line width chars or less */if (len_rem <= line_width) {/* print last line and get out */print_hex_ascii_line(ch, len_rem, offset);break;}}
}

使用方法:

gcc -g pcap_file_parse.c -o pcap_file_parse.c
假设要解析的pcap文件为test.pcap,有两种方法,一种是解析结果直接输出到屏幕上,另一种是写到指定的文件中,分别对应
./pcap_file_parse test.pcap
./pcap_file_parse test.pcap > output.txt
下面是代码运行效果图
应该注意的问题
1.使用wireshark等抓包时,必须存为pcap文件格式,否则上面的代码解析将会出错.参见下面的截图

Ubuntu 14.04 64bit上解析wireshark抓包pcap文件格式和源码实现相关推荐

  1. 在Ubuntu 14.04 64bit上编译并研究State Threads网络线程库源码

    State Threads是一个广受关注的高性能网络线程库,winlin在SRS中做了比较充分的应用,我很遗憾直到现在才精心研究它.下面是我的研究实录,以作备忘. 一.源码编译 下面是在Ubuntu ...

  2. 在Ubuntu 14.04 64bit上安装Markdown和绘图软件Haroopad

    简介 Haroopad:一款让你欲罢不能的Markdown编辑器 身为大程序员,我本来是不需要 Markdown 编辑器的,但是 Haroopad 让我简直欲罢不能,不能再爱更多.跨平台,代码高亮,V ...

  3. 在Ubuntu 14.04 64bit上安装StarUML 2.5版本

    StarUML是来自韩国的一个优秀的UML绘图软件, 原来是免费软件, 现在需要付费购买.当然免费使用功能会有诸多限制. 它支持Windows, Linux和Mac OS等平台. 下面是我在Ubunt ...

  4. 在Ubuntu 14.04 64bit上生成ATS本地离线文档

    下面是在Ubuntu 14.04 64bit上生成ats本地离线文档的方法 首先请安装配置好sphinx环境,参见我前面的博文 http://blog.csdn.net/tao_627/article ...

  5. 在Ubuntu 14.04 64bit上安装Markdown编辑器Remarkble

    目前Markdown已经是非常流行和高效的文档整理和书写工具语言, 我以前接触过, 但是一直没有坚持下来, 这次五一假期期间我强迫自己去熟悉它的语法格式和编辑器, 原来我在Ubuntu 14.04 6 ...

  6. 在Ubuntu 14.04 64bit上安装百度云Linux客户端BCloud

    百度云是一个不错的网盘,Bcloud 是一个 Linux 下超赞的客户端, 官网 github: https://github.com/LiuLang/bcloud-packages 和kwplaye ...

  7. 在ubuntu 14.04 64bit上安装酷我音乐盒Linux客户端kwplayer

    kwplayer 是linux桌面下的轻量级的音乐播放软件, 由LiuLang同学开发, 使用的是Python3+gtk3, 开源的(GPLv3). 它的主要特点有: • 使用了kuwo.cn(酷我音 ...

  8. 在Ubuntu 14.04 64bit上安装numpy和matplotlib库

    机器学习是数据挖掘的一种实现形式,在学习<机器学习实战>过程中,需要python环境中安装好numpy和matplotlib库,特此将我在Ubuntu 14.04 64bit上的摸索过程总 ...

  9. 在Ubuntu 14.04 64bit上进行md5加密编程

    计算指定字符串的md5值是一项很常见的操作,包括使用命令行md5sum,或者在C/C++编程中调用openssl提供的接口函数来进行.下面我们分别阐述如下: 一.在命令行中使用md5校验 计算某个文件 ...

最新文章

  1. 万字长文带你入门 GCN
  2. 人体姿态估计(Human Pose Estimation)技巧方法汇总
  3. dlopen函数的用法
  4. 什么是网络光纤收发器?
  5. 2011 - 12 - 12记录2011 - 12 - 11
  6. git rebase 变基
  7. [Git]Git远程仓库
  8. Banner中利用Jquery隐藏显示下方DIV块
  9. 兜兜转转,回到原点,Hello Mr.my yesterday
  10. Arcgis中的空间数据拓扑理论及规则
  11. 端午节放假安排出来啦,收藏这些端午节海报为端午节活动做准备吧
  12. 计算机课怎么管纪律,作为班主任,班级纪律应该怎么管?丨班级圆桌派
  13. 【CAD】天河云cad,剖面线/细线已经改变图层,颜色却不变的问题
  14. Linux常用命令大全(非常全!!!)
  15. SQL Server 索引优化——重复索引(部分重复)
  16. 穹顶之下——大数据下生活
  17. [整站源码]thinkphp家纺针织床上用品类网站模板+前后端源码
  18. php计算产检时间,预产期计算器 孕期计算器 怀孕孕周期表 产检时间日历 怎么算预产期计算公式...
  19. Java并发编程工具类:CountDownLatch、CyclicBarrier、Semaphore
  20. laravel教程 第一章安装laravel

热门文章

  1. 『Scrapy』爬虫框架入门
  2. 【一】TSP、VRP、VRP模型介绍
  3. TCP/IP协议三次握手与四次握手流程解析
  4. 用python的numpy作线性拟合、多项式拟合、对数拟合
  5. MSSQL 2008里事务的一个问题
  6. 从.NET1.1升级到.NET2.0时出现的PInvokeStackImbalance错误
  7. YOLOv3 训练的各种config文件以及weights文件。
  8. usaco contact
  9. 乐高机器人教室布置图片大全_全国青少年机器人技术等级考试(上海宝山站)顺利举行...
  10. c# 小票打印机打条形码_C#打印小票自带条形码打印