1、Click to edit Master title style,Click to edit Master text styles,Second level,Third level,Fourth level,Fifth level,*,*,Click to edit Master title style,Click to edit Master text styles,Second level,Third level,Fourth level,Fifth level,*,*,*,D,issect L2tp,Wireshark窗口加载,及协议注册请参考解析文档,Wireshark对解析数据包可分
2、成两种模式:,First pass:不建立协议树,直接尝试解析,Second pass:建立协议树,获取详细信息,有显示过滤时,,必须建立协议树,First Pass,1.进入,create_main_windows函数,2.调用main_menu_new函数创建菜单对象,其中调用menus_ init函数进行菜单的初始化,2,菜单初始化后,一旦用户点选某个菜单,gtk_main就会得到点选菜单的item标识,,通过查找列表,,获取相应的函数并回调。,当我们选择Options.时,会回调capture_prep_cb。,capture_prep_cb负责创建并显示Option对话框。其中,出现
3、Options窗口后,点击“Start”就会触发capture_start_cb,该按钮与回调函数的初始化连接过程就是在capture_prep_cb函数里面完成的。,3.点击start后,调用capture_start(capture.c),4.,调用,sync_pipe_start,创建抓包子进程(dumpcap),调用CreatePipe 创建匿名管道、CreateNamedPipe创建命名管道,设置进程通讯为刚才创建的管道、CreatProcess创建抓包进程(win32),调用pipe_input_set_handler函数,将通讯管道与sync_pipe_input_cb回调函数连
4、接起来,一旦有数据返回,则会回调sync_pipe_input_cb,其中,,pipe_input_set_handler,函数中使用了,g_timeout_add,函数而没有使用其后几行的,g_io_add_watch_full,函数。,g_timeout_add,函数通过每,200,毫秒循环检测,io,,一旦有数据,就会触发,pipe_time_cb,函数,这个函数是这样的:,可以看到通过PeekNamedPipe问询IO管道是否有数据然后决定是否回调,如果确认有数据则回调sync_pipe_input_,cb函数。回调sync_pipe_input_cb函数,读取数据,:,5.调用cap
5、ture_input_new_file尝试解析这个临时文件,并初始化一个wtap(capture_opts)结构用于后续解析,并设置成临时文件模式:,调用cf_open打开文件,。cf_open函数调用wtap_open_offline,将临时文件处理交给wiretap模块。如果能够成功识别wtap_open_offline将返回一个wtap结构指针wth,,其中两次调用,file_open函数,,分别获取顺序读取句柄与随机读取句柄:,顺序读取只使用一次,,之后全部操作都是,使用的随机句柄,wtap_open_offline函数成功返回,,到此,打开了文件,init_dissection初始化
6、解析过程所需要的所有数据结构,申请一个,frame,数据队列,,,返回cf_open、cf_start_,tail函数,6.,向主窗口和状态栏发送,capture_cb_capture_,update_started,事件使其更新信息,至此,完成了几项工作:,1、确认dumpcap已经正常工作;,2、已经初始化相关数据结构 ;,3、确认了数据传输使用的文件格式。,7.,再次回调sync_pipe_input_cb返回,此次是,SP_,PACKET_,C,OUNT,类型数据,表明返回的是的数据报文数量,报文个数,8.,调用,capture_input_new_packets,函数去文件,循环,读
7、取新抓到的报文,:,读取单个报文结束后,进入read_packet,调用frame_data_init函数,初始化frame_data结构,开始将第一个报文的frame_data加入到frame_data_sequence队列中去,同时,read_packet中调用add_packet_to_packet_list将该报文加入到报文列表中:,9.add_packet_to_packet_list函数中进行基本信息的解析,解析过程如下:,执行epan_dissect_run 逐层解析开始,:,调用,call_dissector,,注意此时协议树是空指针,(,实际上第一部分是不,会,生成协议树的,
8、可以看到,最后调用了,dissect_frame,:,解析frame信息后,调用dissector_try_unit尝试解析上层协议:,如此逐层解析,当解析完UDP协议后,调用decode_udp_ports,根据端口号(1701)查找下一层协议(应用层)处理句柄dissect_l2tp_udp,,逐层解析,ppp,、ip、udp上层协议,最后查找大小端口对应的协议解析句柄,没有找到。数据作为数据块调用dissect_data处理:,data,处理句柄返,回,尝试解析完成,将从各协议处理句柄层层返回,。调用new_packet_list_append将刚处理完的数据加载到列表上。至此第一个
9、报文处理完毕。(循环处理其他报文),所有报文解析完成后,,wireshark,主界面将,基本信息,会显示,packet list,列表,内,Second Pass,点击任意报文(packet list),将触发new_packet_list_select_cb函数,调用,cf_select_packet,准备解析选中的报文,调用epan_dissect_run开始解析,此步开始与,第一种处理方式中的解析过程相同,,流程基本一致。调用call_dissector,对比第一部分,注意到协议树指针非空,这次要建立完整的协议树了。,其后的解析过程也会传递协议树:,下面,可以看到开始针对特定协议,按照协议格式分配协议树节点数据结构,:,逐个的增加各,个字段,节点,,及下级协议信息:,按照第一部分的流程,逐层解析协议,并增加协议树的节点,,添加完成后协议树如下:,2.,更新主界面,,显示详细协议树信息,结束本次解析。,顶部根节点实际上没有任何内容,只是为了被子节点指向方便,






