winshark重要数据结构

说起来有一些惭愧,研究wireshark有一段时间了,但是对源代码的分析却至今没有什么进展。。。

最初想要研究wireshark是因为我的开题是基于wireshark来做的。

现在有很多抓包工具,wireshark的优势在于完全开源,分析功能强大,但其缺点也很明显,即捕获的数据包存储过于分散,大数据背景下,不能有效的对海量的数据包进行存储分析,因此将wireshark捕获到的数据存储到专门的数据库中是非常必要的。(当然,存储数据只是第一步,接下来还要进行对数据的分析工作)

真正开始分析wireshark了,首先是编译。unbutu下很顺利就编译通过了,但是在windows下却出现各种问题,至今没有编译通过。。。,分析wireshark源代码,在windows下编译通过有必要吗?

后来看关于wireshark的论文,接触到了两个东西。即winpcap、libpcap

winpcap是底层的,在windows上wireshark是依赖于winpcap来截包的,在linux上则是依赖于libpcap。而winpcap又是基于libpcap的设计基础上开发设计的,使用方法也和libpcap基本相同。

那么,我在分析wireshark存储部分源代码的时候有必要看winpcap和libpcap的函数库吗?

到真正看wireshark源代码了,200多M,算上子文件共2000多个,对于一个不是计算机科班出身的我来说,不得不说,有点困难。。 从百度文库上下载了些资料,主要是分析wireshark逻辑功能模块,最有价值的应该是这篇了,如下:

a)  GTK1/2
处理用户的输入输出显示,源码在gtk目录.b)  Core
核心模块,通过函数调用将其他模块连接在一起,源码在根目录c)  Epan
wireshark Packetage Analyzing,包分析引擎,源码在epan目录Protocol-Tree:保存数据包的协议信息,wireshark的协议结构采用树形结构,解析协议报文时只需要从根节点通过函数句柄依次调用各层解析函数即可。Dissectors:在epan/dissector目录下,各种协议解码器,支持700+种协议解析,对于每种协议,解码器都能识别出协议字段(field),并显示出字段值(field value)由于网络协议种类很多,为了使协议和协议间层次关系明显,对数据流里的各个层次的协议能够逐层处理,wireshark系统采用了协议树的方式。Plugins:一些协议解码器以插件形式实现,源码在plugins目录Display-Filters:显示过滤引擎,源码在epan/dfilter目录d)  Capture
捕包引擎,利用libpcap/WinPcap从底层抓取网络数据包,libpcap/WinPcap提供了通用的抓包接口,能从不同类型的网络接口(包括以太网,令牌环网,ATM网等)获取数据包。e)  Wiretap
从文件中读取数据包,支持多种文件格式,源码在wiretap目录f)  Win-/libpcap
Wireshark抓包时依赖的库文件wireshark功能模块3.  wireshark流程分析
1)  初始化
Wireshark的初始化包括一些全局变量的初始化、协议分析引擎的初始化和Gtk相关初始化,显示Ethereal主窗口,等待用户进一步操作。重点就是Epan模块的初始化。
Epan初始化:tvbuff初始化:全局变量tvbuff_mem_chunk指向用memchunk分配的固定大小的空闲内存块,每个内存块是tvbuff_t结构,从空闲内存块中取出后,用来保存原始数据包。协议初始化:全局变量:proto_names proto_short_names proto_filter_names 
以上三个全局变量主要用来判断新注册的协议名是否重复,如果重复,给出提示信息,在协议解析过程中并没有使用。
   协议注册:
   注册协议:将三个参数分别注册给proto_names、proto_short_names、proto_filter_names三个全局变量中,
   注册字段,需要在wireshark协议树显示的报文内容字段。
   协议解析表
   Handoff注册
   将协议与父协议节点关联起来
   Packet(包)初始化
   全局变量:
   frame_handle:协议解析从frame开始,层层解析,直到所有的协议都解析完为止。frame_handle保存了frame协议的handle。
   data_handle:有的协议无法从frame开始,那么就从data开始。原理同frame。 
   读配置文件preference
   读capture filter和display filter文件,分别保存在全局变量capture_filter和display_filter中。
   读disabled protocols文件,保存全局变量global_disabled_protos和disabled_protos中
   初始化全局变量cfile
   Cfile是个重要的变量,数据类型为capture file,它保存了数据包的所有信息,
   取得命令行启动时,参数列表,并进行相应的处理2)  处理流程
Wireshark初始化完成以后进入实际处理阶段,主程序创建抓包进程,捕包进程和主程序是通过PIPE进行传递数据的,主程序把抓取的数据写入临时文件,通过函数add_packet_to_packet_list将数据包加入包列表。处理时,主程序从列表中选取一个数据包,提取该数据包中的数据填写在数据结构中,最后调用协议解析函数epan_dissect_run进行处理,从epan_dissect_run开始,是实际的协议解析过程,
下面以HTTP协议报文为例,流程如下:
a)  解析frame层
调用函数dissect_frame对frame层进行解析,并在协议树上填充相应字段信息。函数最后会判断是否有上层协议封装,如果有则调用函数dissector_try_port在协议树上查找对应的解析函数,这里函数dissector_try_port根据pinfo->fd->lnk_t查找对应的上层协议处理函数,pinfo->fd->lnk_t值为1,上层封装协议为以太网协议,全局结构体指针变量dissector_handle当前的协议解析引擎句柄置为dissect_eth_maybefcs,至此,frame层解析结束。
b)  解析以太网层
函数call_dissector_work根据dissector_handle调用frame上层协议解析函数dissect_eth_maybefcs对以太网层进行解析,并在协议树上填充相应字段,包括目的MAC地址和以太网上层协议类型等信息。函数最后会判断是否有上层协议封装,如果有则调用函数dissector_try_port在协议树上查找对应的解析函数,这里函数dissector_try_port根据etype查找对应的上层协议处理函数,以太网字段etype为0800的报文是ip报文,上层封装协议为IP协议,全局结构体指针变量dissector_handle当前的协议解析引擎句柄置为dissect_ip,至此,以太网层解析结束。
c)  解析IP层
函数call_dissector_work根据dissector_handle调用以太网上层协议解析函数dissect_ip对以太网层进行解析,并在协议树上填充相应字段,包括版本号,源地址,目的地址等信息。函数最后会判断是否有上层协议封装,如果有则调用函数dissector_try_port在协议树上查找对应的解析函数,这里函数dissector_try_port根据nxt (nxt = iph->ip_p)查找对应的上层协议处理函数,以太网字段nxt为06的报文是TCP报文,上层封装协议为TCP协议,全局结构体指针变量dissector_handle当前的协议解析引擎句柄置为dissect_tcp,至此,IP层解析结束。
d)  解析TCP层
函数call_dissector_work根据dissector_handle调用以太网上层协议解析函数dissect_tcp对TCP层进行解析,包括对TCP头的解析和选项字段的解析,并在协议树上填充相应字段,包括源端口,目的端口,标志位等信息。函数最后会判断是否有上层协议封装,如果有则调用函数dissector_try_port在协议树上查找对应的解析函数,这里函数dissector_try_port根据port查找对应的上层协议处理函数,将源端口和目的端口分别赋值给low_port和high_port,根据low_port和high_port分别匹配上层协议解析函数,port为80的报文是HTTP报文,上层封装协议为HTTP协议,全局结构体指针变量dissector_handle当前的协议解析引擎句柄置为dissect_http,至此,TCP层解析结束。
e)  解析HTTP层
至此wireshark进入应用层协议检测阶段,wireshark解析dissect_http函数中注册的字段,并提取相应的字段值添加到协议树中,应用层的具体解析流程将在下面介绍。HTTP协议具体函数调用过程参见: 重要的数据结构struct _epan_dissect_t {tvbuff_t    *tvb;//用来保存原始数据包proto_tree  *tree;//协议树结构packet_info pi;// 包括各种关于数据包和协议显示的相关信息
};/** Each proto_tree, proto_item is one of these. */
typedef struct _proto_node {struct _proto_node *first_child;//协议树节点的第一个子节点指针struct _proto_node *last_child; //协议树节点的最后一个子节点指针struct _proto_node *next; //协议树节点的下一个节点指针struct _proto_node *parent;//父节点指针field_info  *finfo;//保存当前协议要显示的地段tree_data_t *tree_data;//协议树信息
} proto_node;typedef struct _packet_info {const char *current_proto;    //当前正在解析的协议名称column_info *cinfo;       //wireshark显示的信息frame_data *fd;//现在分析的原始数据指针union wtap_pseudo_header *pseudo_header;//frame类型信息GSList *data_src;     /*frame层信息 */address dl_src;       /* 源MAC */address dl_dst;       /*目的MAC */address net_src;      /* 源IP */address net_dst;      /*目的IP */address src;          /*源IP */address dst;          /*目的IP */guint32 ethertype;        /*以太网类型字段*/guint32 ipproto;      /* IP协议类型*/guint32 ipxptype;     /* IPX 包类型 */guint32 mpls_label;       /* MPLS包标签*/circuit_type ctype;       guint32 circuit_id;       /*环路ID */const char *noreassembly_reason;  /* 重组失败原因*/gboolean fragmented;      /*为真表示未分片*/gboolean in_error_pkt;    /*错误包标志*/port_type ptype;      /*端口类型 */guint32 srcport;      /*源端口*/guint32 destport;     /*目的端口*/guint32 match_port;           /*进行解析函数匹配时的匹配端口*/const char *match_string; /*调用子解析引擎时匹配的协议字段指针*/guint16 can_desegment;    /* 能否分段标志*/guint16 saved_can_desegment;  int desegment_offset;     /*分段大小*/
#define DESEGMENT_ONE_MORE_SEGMENT 0x0fffffff
#define DESEGMENT_UNTIL_FIN        0x0ffffffeguint32 desegment_len;    guint16 want_pdu_tracking;    guint32 bytes_until_next_pdu;int     iplen;                /*IP包总长*/int     iphdrlen;             /*IP头长度*/int     p2p_dir;              guint16 oxid;                 /* next 2 fields reqd to identify fibre */guint16 rxid;                 /* channel conversations */guint8  r_ctl;                /* R_CTL field in Fibre Channel Protocol */guint8  sof_eof;             guint16 src_idx;              /* Source port index (Cisco MDS-specific) */guint16 dst_idx;              /* Dest port index (Cisco MDS-specific) */guint16 vsan;                 /* Fibre channel/Cisco MDS-specific *//* Extra data for DCERPC handling and tracking of context ids */guint16 dcectxid;             /* Context ID (DCERPC-specific) */int     dcetransporttype;guint16 dcetransportsalt; /* fid: if transporttype==DCE_CN_TRANSPORT_SMBPIPE */
#define DECRYPT_GSSAPI_NORMAL   1
#define DECRYPT_GSSAPI_DCE  2guint16 decrypt_gssapi_tvb;tvbuff_t *gssapi_wrap_tvb;tvbuff_t *gssapi_encrypted_tvb;tvbuff_t *gssapi_decrypted_tvb;gboolean gssapi_data_encrypted;guint32 ppid;  /* SCTP PPI of current DATA chunk */guint32 ppids[MAX_NUMBER_OF_PPIDS]; /* The first NUMBER_OF_PPIDS PPIDS which are present * in the SCTP packet*/void    *private_data;    /* pointer to data passed from one dissector to another *//* TODO: Use emem_strbuf_t instead */GString *layer_names;     /* layers of each protocol */guint16 link_number;guint8  annex_a_used;guint16 profinet_type;    /* the type of PROFINET packet (0: not a PROFINET packet) */void *profinet_conv;     /* the PROFINET conversation data (NULL: not a PROFINET packet) */void *usb_conv_info;void *tcp_tree;       /* proto_tree for the tcp layer */const char *dcerpc_procedure_name;    /* Used by PIDL to store the name of the current dcerpc procedure */struct _sccp_msg_info_t* sccp_info;guint16 clnp_srcref;      /* clnp/cotp source reference (can't use srcport, this would confuse tpkt) */guint16 clnp_dstref;      /* clnp/cotp destination reference (can't use dstport, this would confuse tpkt) */guint16 zbee_cluster_id;  /* ZigBee cluster ID, an application-specific message identifier that* happens to be included in the transport (APS) layer header.*/guint8 zbee_stack_vers;     int link_dir; /* 3GPP messages are sometime different UP link(UL) or Downlink(DL)*/
} packet_info;

因为我的主要工作是修改wireshark存储部分源代码,还有必要从main开始分析吗?看到一层层的调用,要调晕了。。。。

博客写的有点乱了,总之,不知道如何开始。。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/385055.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言写数据库(二)

简单的实现增删查改的操作后,实现了一个先读写其中一个表的某两项内容,再把相关字符段写入到另外一张表中去。涉及到查询和插入两个步骤。 其中还涉及到汉字的读写和插入,会有字符的操作产生乱码。所以要先保证mysql的汉字字符编码&#xff0…

wireshark源代码分析

各位亲,不是我不想回复你们的问题。是我也不了解。不能误导。希望大家相互帮助。看看能否帮那些提问的小盆友们回复一下呢? 这些都是转载的,如果实在没有办法,可以打开链接到原作者哪里去提问试试看。。。 经过多次尝试&#xf…

C语言写数据库(三)

遇到的问题以及解决思路方法 1.外部导入数据库文件 进入mysql,创建数据库sh_robot source /home/exbot/sh_robot.sql 查看数据库编码格式 show variables like “%char%”; 2.数据库插入操作 进入相关数据库:use 数据库名; 查询存在该表是否存…

Makefile(一)

在一个文件夹中建一个c文件 //main.c #include<stdio.h> int main() {printf("version 1.0");return 0; } 在当前目录下编写makefile文件 //makefile: test : main.o //一种依赖关系声明&#xff0c;生成test可执行程序需要以来main.o文件gcc -o test main.…

Defunct进程 僵尸进程

在测试基于 DirectFBGstreamer 的视频联播系统的一个 Demo 的时候&#xff0c;其中大量使用 system 调用的语句&#xff0c;例如在 menu 代码中的 system("./play") &#xff0c;而且多次执行&#xff0c;这种情况下&#xff0c;在 ps -ef 列表中出现了大量的 defunc…

make文件基础用法

参照&#xff1a;https://www.jianshu.com/p/0b2a7cb9a469 创建工作目录&#xff0c;包含一下文件 main.cperson.cb.hc.h/*** c.h ***/ //this is c.h /*** b.h ***/ //this is b.h /*** main.c ***/ #include<stdio.h> //#include"a1.h" //#include"b.h&…

一个Linux下C线程池的实现(转)

1.线程池基本原理 在传统服务器结构中, 常是 有一个总的 监听线程监听有没有新的用户连接服务器, 每当有一个新的 用户进入, 服务器就开启一个新的线程用户处理这 个用户的数据包。这个线程只服务于这个用户 , 当 用户与服务器端关闭连接以后, 服务器端销毁这个线程。然而频繁地…

二维数组作为函数参数

#include<stdio.h> //#include<> //二位数组作为函数参数时&#xff0c;可以不指定第一个下标 void print_buf(int (*p)[3],int a,int b) //void print_buf(int p[][3],int a,int b) {int i,j;for(i 0 ; i < a; i){for(j 0; j < b; j){printf("p[%…

mystrcat

#include<stdio.h> //如果一个数组做为函数的形参传递&#xff0c;那么数组可以在被调用的函数中修改 //有时候不希望这个事发生&#xff0c;所以对形参采用const参数 //size_t strlen(const char *s); //strcpy(char* s1,const char* s2); void mystrcat(char *s1,cons…

关于非阻塞的recv的时候返回的处理

注意recv&#xff08;&#xff09;如果读到数据为0&#xff0c;那么就表示文件结束了&#xff0c;如果在读的过程中遇到了中断那么会返回-1&#xff0c;同时置errno为EINTR。 因此判断recv的条件&#xff1a; 如果read返回<0 如果0 表示文件结束&…

带参程序

windows环境 #include<stdio.h>int main(int argc, char *argv[]) {printf("argc %d\n", argc);for (int i 0; i < argc; i){printf("argv[%d] %s\n",i, argv[i]);}system("pause");return 0; } windows环境下&#xff0c;带参函数…

Ubuntu安装mysql步骤

1.打开终端&#xff0c;输入&#xff1a; sudo apt-get updata 输入root用户密码 2.更新完毕后&#xff0c;输入 sudo apt-get install mysql-server ubuntu14.04安装中间会让你设置密码&#xff0c;输入密码后点击确认(mysql123) 3.安装结束后&#xff0c;查看端口号是否开启 …

Pthread创建线程后必须使用join或detach释放线程资源

这两天在看Pthread 资料的时候&#xff0c;无意中看到这样一句话(man pthread_detach): Either pthread_join(3) or pthread_detach() should be called for each thread that an application creates, so that system resources for the thread can be released. …

二维数组求平均值(指针的使用)

#include<stdio.h>int main() {int buf[3][5] {{1,2,3,4,5},{4,5,6,7,8},{7,8,9,10,11}};int i;int j;//求行平均值 for(i 0; i < 3; i){int sum 0;for(j 0; j < 5; j){sum (*(*(buf i) j));}printf("sum %d\n",sum/5);}//求列平均值for(i 0; i …

linux终端关闭时为什么会导致在其上启动的进程退出?

现象 经常在linux下开发的人应该都有这样的经验&#xff0c;就是在终端上启动的程序&#xff0c;在关闭终端时&#xff0c;这个程序的进程也被一起关闭了。看下面这个程序&#xff0c;为了使进程永远运行&#xff0c;在输出helloworld后&#xff0c;循环调用sleep&#xff1a; …

二维数组做函数参数传递

#include<stdio.h> //#include<> //二位数组作为函数参数时&#xff0c;可以不指定第一个下标 void print_buf(int (*p)[3],int a,int b) //void print_buf(int p[][3],int a,int b) {int i,j;for(i 0 ; i < a; i){for(j 0; j < b; j){printf("p[%…

libevent源码深度剖析

第一章 1&#xff0c;前言 Libevent是一个轻量级的开源高性能网络库&#xff0c;使用者众多&#xff0c;研究者更甚&#xff0c;相关文章也不少。写这一系列文章的用意在于&#xff0c;一则分享心得&#xff1b;二则对libevent代码和设计思想做系统的、更深层次的分析&#xff…

函数返回指针类型(strchr函数)

#include<stdio.h> #include<string.h> char *mystrchr(char *s,char c) {while(*s){if(*s c){return s;}s;}return NULL; }int main() {char str[100] "hello world";//char* s strchr(str,a);char *s mystrchr(str,e);//返回ello world字符串 prin…

函数与指针

#include<stdio.h>int add(int a,int b) {return ab; }int main() {void *p(int,char *); //声明了一个函数 &#xff0c;函数名为p&#xff0c;函数返回值为void*,函数的 void (*p)(int,char *);//定义了一个指向参数为int和char*返回值为void的函数指针//定义一个参数为…

使用指针在函数中交换数值

#include<stdio.h>void swap(int* a,int *b) {/*int temp *a;*a * b;*b temp;*/*a *b;*b *a - *b;*a *a - *b; }int main() {int a 10;int b 20;swap(&a,&b);printf("a %d,b %d\n",a,b);} 转载于:https://www.cnblogs.com/wanghao-boke/p/1…