1. General analysis
When Wireshark is started, all parsers are initialized and registered. The information to be registered includes the protocol name, the information for each field, the keyword to filter, the underlying protocol and port to associate with (handoff), and so on. In the parsing process, each parser is responsible for parsing its own protocol part, and then passing the upper package data to the subsequent protocol parser, thus constituting a complete chain of protocol parsing.
The top of the analytic chain is the frame parser, which is responsible for parsing the Pcap frame header. The subsequent invocation of which parser, is to register handoff information through the upper layer protocol is written in the current Protocol hash table to find.
For example, consider the IPv4 parser with a hash table, which stores the information in the following table. When it resolves the IPv4 header, it can be based on the obtained protocol number field, such as 6, then it can find the subsequent parser TCP from this hash table.
Protocol number |
Parser pointer |
6 |
*tcp |
17 |
*udp |
...... |
There are 3 kinds of analytic tables in Wireshark, namely, String table, Integer table and heuristic parsing table. As shown in the following:
The following is an example of an IP protocol that describes its registration process.
The related important data structures and global variables are as follows.
Proto.c
/*Name hashtables for fast detection of duplicate names*/Staticghashtable* Proto_names =NULL;Staticghashtable* Proto_short_names =NULL;Staticghashtable* 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*/intProto_register_protocol (Const Char*name,Const Char*short_name,Const Char*filter_name);
Three global hash tables are used to save the protocol name, the protocol abbreviation, and the protocol name for the filter, respectively.
PACKET.C:
structdissector_table {ghashtable*hash_table; Gslist*Dissector_handles; Const Char*Ui_name; ftenum_t type; int Base;};StaticGhashtable *dissector_tables =NULL;/** List of registered dissectors.*/StaticGhashtable *registered_dissectors =NULL;StaticGhashtable *heur_dissector_lists =NULL;/*Register a dissector by name.*/Dissector_handle_tregister_dissector (Const Char*name, dissector_t Dissector,Const intproto);/** A protocol uses this function to register A heuristic sub-dissector list. * Call this in the parent dissectors prot O_register function. * * @param name The name of this protocol * @param list the list of heuristic sub-dissectors to be registered*/voidRegister_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,Constftenum_t type,Const int Base);
Dissector_tables can be said to be a "hash table", which parses the table name as a key (such as "Ip.proto"), with the dissector_table structure pointer as the value. The hash table in dissector_table is a pointer to an unsigned number as a key (such as a protocol number, as a pointer to the parameter of the GLib hash table API), with the parser handle as the value; Heur_dissector_lists is a heuristic to parse something related, This question is left to be studied later; Registered_dissectors is a parser hash table, which takes the parser name as a key (such as "IP"), with the parser handle as the value.
Packet.h:
struct dissector_table *dissector_table_t;
PACKET-IP.C:
static dissector_table_t ip_dissector_table;
In the PROTO_REGISTER_IP function:
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 This function in packet.c, within this function, creates a hash table called "Ip.proto". After parsing the IP protocol, the table is queried, the next parser is found, and the parsing of subsequent data is handed over to it.
Within the PACKET-IP.C,DISSECT_IP function:
Dissector_try_uint_new (ip_dissector_table, NXT, NEXT_TVB, pinfo, parent_tree, TRUE, IPH)
PACKET.C:
/**/constconstvoid *data)
In the Dissector_try_uint_new function, the parser handle corresponding to the protocol number is found and used to parse the rest of the data.
2. Heuristic (heuristic) parsing
Todo
3. Reference
Wireshark Development Guide 6th Chapter "How Wireshark Works"
"Wireshark" Protocol resolution