wireshark协议解析器源码分析封装调用

wireshark协议解析器源码分析封装调⽤
源码分析
Wireshark启动时,所有解析器进⾏初始化和注册。要注册的信息包括协议名称、各个字段的信息、过滤⽤的关键字、要关联的下层协议与端⼝(handoff)等。在解析过程,每个解析器负责解析⾃⼰的协议部分, 然后把上层封装数据传递给后续协议解析器,这样就构成⼀个完整的协议解析链条。
解析链条的最上端是Frame解析器,它负责解析pcap帧头。后续该调⽤哪个解析器,是通过上层协议注册handoff信息时写在当前协议的hash表来查的。
例如,考虑ipv4解析器有⼀个hash表,⾥⾯存储的信息形如下表。当它解析完ipv4⾸部后,就可以根据得到的协议号字段,⽐如6,那么它就能从此hash表中到后续解析器tcp。
协议号解析器指针
6*tcp
17*udp
……
Wireshark中实际的解析表有3种,分别是字符串表,整数表和启发式解析表。如下图所⽰:
下⾯以ip协议为例,说明⼀下它的注册过程。
相关的重要数据结构与全局变量如下。
proto.c
/* Name hashtables for fast detection of duplicate names */
static GHashTable* proto_names        = NULL;
static GHashTable* proto_short_names  = NULL;
static GHashTable* proto_filter_names = NULL;
/** Register a new protocol.
@param name the full name of the new protocol
@param short_name abbreviated name of the new protocol
@param filter_name protocol name used for a display filter string
@return the new protocol handle */
int
proto_register_protocol(const char *name, const char *short_name, const char *filter_name);
三个全局的哈希表分别⽤于保存协议名称、协议缩略名和⽤于过滤器的协议名。
packet.c:
struct dissector_table {
GHashTable    *hash_table;
GSList    *dissector_handles;
粒子const char    *ui_name;
ftenum_t    type;
int        base;
};
static GHashTable *dissector_tables = NULL;
/*
* List of registered dissectors.
*/导丝男士
recent文件夹static GHashTable *registered_dissectors = NULL;
static GHashTable *heur_dissector_lists = NULL;
/* Register a dissector by name. */
dissector_handle_t
register_dissector(const char *name, dissector_t dissector, const int proto);
/** A protocol uses this function to register a heuristic sub-dissector list.
*  Call this in the parent dissectors proto_register function.
*
* @param name the name of this protocol
* @param list the list of heuristic sub-dissectors to be registered
*/
void register_heur_dissector_list(const char *name,
heur_dissector_list_t *list);
/* a protocol uses the function to register a sub-dissector table */
dissector_table_t register_dissector_table(const char *name, const char *ui_name, const ftenum_t type, const int base);
dissector_tables可以说是“哈希表的哈希表”,它以解析表名为键(如“ip.proto”),以dissector_table结构指针为值。在dissector_table中的哈希表以⽆符号数的指针为键(如协议号,为指针是glib hash表API的参数要求),以解析器handle为值;
heur_dissector_lists是启发式解析相关的东西,这个问题留待以后研究;registered_dissectors是解析器哈希表,它以解析器名为键(如”ip”),以解析器句柄为值。
packet.h:
typedef struct dissector_table *dissector_table_t;
packet-ip.c:
static dissector_table_t ip_dissector_table;
proto_register_ip函数中:
proto_ip = proto_register_protocol("Internet Protocol Version 4", "IPv4", "ip");
...
/* subdissector code */
ip_dissector_table = register_dissector_table("ip.proto", "IP protocol", FT_UINT8, BASE_DEC);
register_heur_dissector_list("ip", &heur_subdissector_list);
...
register_dissector("ip", dissect_ip, proto_ip);
register_init_routine(ip_defragment_init);
ip_tap = register_tap("ip");
register_dissector_table这个函数在packet.c中,在此函数内,创建了名为“ip.proto”的哈希表。解析ip协议后,会查询这个表,出下⼀个解析器,并将后续数据的解析移交给它。
packet-ip.c,dissect_ip函数内:
dissector_try_uint_new(ip_dissector_table, nxt, next_tvb, pinfo,
parent_tree, TRUE, iph)
packet.c:
/* Look for a given value in a given uint dissector table and, if found, call the dissector with the arguments supplied, and return TRUE, otherwise return FALSE. */ gboolean
dissector_try_uint_new(dissector_table_t sub_dissectors, const guint32 uint_val, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const gboolean add_proto_nam 在dissector_try_uint_new函数中,会到协议号对应的解析器句柄,并使⽤它解析其余数据。
涉及到的函数与数据结构
⾸先我们得知道需要调⽤哪些函数。通过调试⾃⼰编译的wireshark,我发现如果要实现简单的协议解析,主要只需要以下⼏个函数(源码位
置均相对于wireshark源码主⽬录⽽⾔):
函 数功 能      源码位置
epan_init  初始化协议解析库epan/epan.h
epan_cleanup清理协议解析库同上
epan_dissect_new创建协议解析数据结构edt同上
epan_dissect_run执⾏协议解析同上
epan_dissect_free销毁协议解析数据结构edt同上
init_dissection初始化数据包级协议解析epan/packet.h
cleanup_dissection 清理数据包级协议解析 同上
除此之外,还需要导出⼀些辅助的函数,如register_all_protocols, register_all_protocol_handoffs,proto_item_fill_label等等。
不仅如此,还需要熟悉协议解析过程所涉及到的⼀些数据结构,主要有:
数据结构功 能      源码位置
epan_dissect_t  协议解析信息,保存协议数据及协议解析树epan/epan.h; epan/epan_dissect.h
field_info协议字段信息epan/proto.h
header_field_info协议⾸部字段信息同上
proto_tree/proto_node协议树同上
frame_data单帧(数据包)信息epan/frame_data.h
wtap_pseudo_header wtap伪⾸部,主要是链路层协议信息wiretap/wtap.h
以上就是⼀些主要的函数及数据结构。实际的协议解析过程中,可能会涉及到更多的函数及数据结构,这⾥就不多说了,具体可以查看
wireshark源码。如果对于某些函数,或者解析过程有不了解的,也可以⾃⼰编译wireshark,然后调试它。
代码实现黎塘论坛
知道原理及所需的函数后,就可以编码实现了。环境的配置等基础知识,本系列前⼀篇已经讲过了。
我继续⽤Win32 Console⼯程来写这个⽰例。我这个⽰例代码分为两个部分:
⼀、wireshark导出函数及简单的封装;
⼆、实际解析代码
第⼀个部分分成wireshark.h和wireshark.cpp两个⽂件。第⼆部分为dissector.cpp,其中也包括了main函数。wireshark导出函数及简单封装
没什么好说的,主要就是所需函数的声明,以及动态调⽤代码。
wireshark.h:
/*
* wireshark协议解析相关的导出函数声明,以及简单函数封装
*
* Copyright (c) 2013 赵⼦清, All rights reserved.
*
*/
#ifndef  __WIRESHARK_H__
#define  __WIRESHARK_H__
// see \wireshark-1.8., #481
#define WS_VAR_IMPORT      __declspec(dllimport) extern
// see \wireshark-1.8., #482
#define WS_MSVC_NORETURN    __declspec(noreturn)
#ifdef  TRY
#undef  TRY
#endif
#ifdef  CATCH
#undef  CATCH
#endif
#ifdef  CATCH_ALL
#undef  CATCH_ALL
#endif
#ifdef  THROW
#undef  THROW
#endif
// wireshark源码头⽂件
#include "epan/epan.h"
#include "epan/epan_dissect.h"
#include "epan/proto.h"
#include "epan/packet_info.h"
#include "epan/frame_data.h"
#include "epan/packet.h"
#include <Windows.h>
#define CHECK(x) if(!(x)) return FALSE;
/* \register.h -------------------------------------------------------------------------*/
typedef void (*register_cb) (register_action_e action, const char *message, gpointer client_data);
typedef void (*f_register_all_protocols) (register_cb cb, gpointer client_data);
typedef void (*f_register_all_protocol_handoffs) (register_cb cb, gpointer client_data);
typedef void (*f_register_all_tap_listeners)(void);
/
*--------------------------------------------------------------------------------------*/
/* \epan\packet.h ----------------------------------------------------------------------*/
typedef void (*f_init_dissection) (void);
typedef void (*f_init_dissection) (void);
typedef void (*f_cleanup_dissection) (void);
/*--------------------------------------------------------------------------------------*/
/* \epan\epan.h -------------------------------------------------------------------------*/
typedef void (*f_epan_init) (void (*register_all_protocols)(register_cb cb, gpointer client_data),                            void (*register_all_handoffs)(register_cb cb, gpointer client_data),
register_cb cb,
void *client_data,
void (*report_failure)(const char *, va_list),
void (*report_open_failure)(const char *, int, gboolean),
void (*report_read_failure)(const char *, int));
typedef void (*f_epan_cleanup) (void);
typedef epan_dissect_t* (*f_epan_dissect_new) (gboolean create_proto_tree,
gboolean proto_tree_visible);
typedef void (*f_epan_dissect_run) (epan_dissect_t *edt, void* pseudo_header,
const guint8* data, frame_data *fd, column_info *cinfo);
typedef void (*f_epan_dissect_free) (epan_dissect_t* edt);乙炔雌二醇
typedef void (*f_epan_dissect_fill_in_columns) (epan_dissect_t *edt);
/*--------------------------------------------------------------------------------------*/
/* \epan\proto.h -----------------------------------------------------------------------*/
typedef void (*f_proto_item_fill_label) (field_info *fi, gchar *label_str);
/*--------------------------------------------------------------------------------------*/
extern f_epan_init                            ws_epan_init;
extern f_epan_cleanup                        ws_epan_cleanup;
extern f_register_all_protocols                ws_register_all_protocols;
extern f_register_all_protocol_handoffs        ws_register_all_protocol_handoffs;
extern f_init_dissection                    ws_init_dissection;
extern f_cleanup_dissection                    ws_cleanup_dissection;
extern f_epan_dissect_new                    ws_epan_dissect_new;
extern f_epan_dissect_run                    ws_epan_dissect_run;
extern f_epan_dissect_free                    ws_epan_dissect_free;
extern f_proto_item_fill_label                ws_proto_item_fill_label;
HINSTANCE  LoadWiresharkDLL(const TCHAR* szDLLPath);
政协提案BOOL  FreeWiresharkDLL(HMODULE hModule);
BOOL  GetWiresharkFunctions(HMODULE hDLL);
#endif /* WIRESHARK_H_ */
wireshark.cpp:

本文发布于:2024-09-22 07:03:37,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/398475.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:协议   解析   解析器   函数   信息   过程   数据结构
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议