From Michael Mann via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6377, with...
[obnox/wireshark/wip.git] / doc / README.heuristic
1 $Revision: 25920 $
2 $Date: 2008-08-04 22:41:43 +0200 (Mo, 04 Aug 2008) $
3 $Author: ulfl $
4
5
6 This file is a HOWTO for Wireshark developers. It describes how Wireshark 
7 heuristic protocol dissectors work and how to write them.
8
9 This file is compiled to give in depth information on Wireshark.
10 It is by no means all inclusive and complete. Please feel free to send
11 remarks and patches to the developer mailing list.
12
13
14 Prerequisites
15 -------------
16 As this file is an addition to README.developer, it is essential to read 
17 and understand that document first.
18
19
20 Why heuristic dissectors?
21 -------------------------
22 When Wireshark "receives" a packet, it has to find the right dissector to 
23 start decoding the packet data. Often this can be done by known conventions, 
24 e.g. the Ethernet type 0x0800 means "IP on top of Ethernet" - an easy and 
25 reliable match for Wireshark.
26
27 Unfortunately, these conventions are not always available, or (accidentally 
28 or knowingly) some protocols don't care about those conventions and "reuse" 
29 existing "magic numbers / tokens".
30
31 For example TCP defines port 80 only for the use of HTTP traffic. But, this 
32 convention doesn't prevent anyone from using TCP port 80 for some different 
33 protocol, or on the other hand using HTTP on a port number different than 80.
34
35 To solve this problem, Wireshark introduced the so called heuristic dissector 
36 mechanism to try to deal with these problems.
37
38
39 How Wireshark uses heuristic dissectors?
40 ----------------------------------------
41 While Wireshark starts, heuristic dissectors (HD) register themselves slightly 
42 different than "normal" dissectors, e.g. a HD can ask for any TCP packet, as 
43 it *may* contain interesting packet data for this dissector. In reality more 
44 than one HD will exist for e.g. TCP packet data.
45
46 So if Wireshark has to decode TCP packet data, it will first try to find a 
47 dissector registered directly for the TCP port used in that packet. If it 
48 finds such a registered dissector it will just hand over the packet data to it.
49
50 In case there is no such "normal" dissector, WS will hand over the packet data 
51 to the first matching HD. Now the HD will look into the data and decide if that 
52 data looks like something the dissector "is interested in". The return value
53 signals WS if the HD processed the data (so WS can stop working on that packet)
54 or if the heuristic didn't match (so WS tries the next HD until one matches -
55 or the data simply can't be processed).
56
57 Note that it is possible to configure WS through preference settings so that it
58 hands off a packet to the heuristic dissectors before the "normal" dissectors
59 are called. This allows the HD the chance to receive packets and process them
60 differently than they otherwise would be. Of course if no HD is interested in
61 the packet, then the packet will ultimately get handed off to the "normal"
62 dissector as if the HD wasn't involved at all. As of this writing, the DCCP,
63 SCTP, TCP, TIPC and UDP dissectors all provide this capability via their
64 "Try heuristic sub-dissectors first" preference, but none of them have this
65 option enabled by default.
66
67
68 How do these heuristics work?
69 -----------------------------
70 Difficult to give a general answer here. The usual heuristic works as follows:
71
72 A HD looks into the first few packet bytes and searches for common patterns that 
73 are specific to the protocol in question. Most protocols starts with a 
74 specific header, so a specific pattern may look like (synthetic example):
75
76 1) first byte must be 0x42
77 2) second byte is a type field and can only contain values between 0x20 - 0x33
78 3) third byte is a flag field, where the lower 4 bits always contain the value 0
79 4) fourth and fifth bytes contain a 16 bit length field, where the value can't 
80    be larger than 10000 bytes
81
82 So the heuristic dissector will check incoming packet data for all of the 
83 4 above conditions, and only if all of the four conditions are true there is a 
84 good chance that the packet really contains the expected protocol - and the 
85 dissector continues to decode the packet data. If one condition fails, it's 
86 very certainly not the protocol in question and the dissector returns to WS 
87 immediately "this is not my protocol" - maybe some other heuristic dissector 
88 is interested!
89
90 Obviously, this is *not* 100% bullet proof, but it's the best WS can offer to
91 its users here - and improving the heuristic is always possible if it turns out
92 that it's not good enough to distinguish between two given protocols.
93
94
95 Heuristic Code Example
96 ----------------------
97 You can find a lot of code examples in the wireshark sources, e.g.:
98 grep -l heur_dissector_add epan/dissectors/*.c
99 returns (currently) 68 files.
100
101 For the above example criteria, the following code example might do the work 
102 (combine this with the dissector skeleton in README.developer):
103
104 XXX - please note: The following code examples were not tried in reality, 
105 please report problems to the dev-list!
106
107 static gboolean dissect_PROTOABBREV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
108 {
109 ...
110
111 /* 1) first byte must be 0x42 */
112 if ( tvb_get_guint8(tvb, 0) != 0x42 )
113     return (FALSE);
114
115 /* 2) second byte is a type field and only can contain values between 0x20-0x33 */
116 if ( tvb_get_guint8(tvb, 1) < 0x20 || tvb_get_guint8(tvb, 1) > 0x33 )
117     return (FALSE);
118  
119 /* 3) third byte is a flag field, where the lower 4 bits always contain the value 0 */
120 if ( tvb_get_guint8(tvb, 2) & 0x0f )
121     return (FALSE);
122
123 /* 4) fourth and fifth bytes contains a 16 bit length field, where the value can't be longer than 10000 bytes */
124 /* Assumes network byte order */
125 if ( tvb_get_ntohs(tvb, 3) > 10000 )
126     return (FALSE);
127  
128 /* Assume it's your packet and do dissection */
129 ...
130
131 return (TRUE);
132 }
133
134
135 void
136 proto_reg_handoff_PROTOABBREV(void)
137 {
138     static int PROTOABBREV_inited = FALSE;
139  
140     if ( !PROTOABBREV_inited )
141     {
142         /* register as heuristic dissector for both TCP and UDP */
143         heur_dissector_add("tcp", dissect_PROTOABBREV, proto_PROTOABBREV);
144         heur_dissector_add("udp", dissect_PROTOABBREV, proto_PROTOABBREV);
145     }
146 }
147
148
149 Please note, that registering a heuristic dissector is only possible for a 
150 small variety of protocols. In most cases a heuristic is not needed, and 
151 adding the support would only add unused code to the dissector.
152
153 TCP and UDP are prominent examples that support HDs, as there seems to be a
154 tendency to reuse known port numbers for new protocols. But TCP and UDP are
155 not the only dissectors that provide support for HDs.  You can find more
156 examples by searching the Wireshark sources as follows:
157 grep -l register_heur_dissector_list epan/dissectors/packet-*.c
158 returns (currently) 25 files.
159
160 It's possible to write a dissector to be a dual heuristic/normal dissector.
161 In that the case, dissect_PROTOABBREV should return an int with the number of 
162 bytes dissected by your protocol rather than simply returning TRUE. If 
163 heuristics fail, still just return 0.
164
165
166 static int dissect_PROTOABBREV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
167 {
168 ...
169
170 /* 1) first byte must be 0x42 */
171 if ( tvb_get_guint8(tvb, 0) != 0x42 )
172     return 0;
173
174 /* 2) second byte is a type field and only can contain values between 0x20-0x33 */
175 if ( tvb_get_guint8(tvb, 1) < 0x20 || tvb_get_guint8(tvb, 1) > 0x33 )
176     return 0;
177  
178 /* 3) third byte is a flag field, where the lower 4 bits always contain the value 0 */
179 if ( tvb_get_guint8(tvb, 2) & 0x0f )
180     return 0;
181
182 /* 4) fourth and fifth bytes contains a 16 bit length field, where the value can't be longer than 10000 bytes */
183 /* Assumes network byte order */
184 if ( tvb_get_ntohs(tvb, 3) > 10000 )
185     return 0;
186  
187 /* Assume it's your packet and do dissection */
188 ...
189
190 return number_of_bytes_dissected;
191 }
192
193 void
194 proto_reg_handoff_PROTOABBREV(void)
195 {
196     static int PROTOABBREV_inited = FALSE;
197     dissector_handle_t PROTOABBREV_handle;
198  
199     if ( !PROTOABBREV_inited )
200     {
201         /* register as heuristic dissector for both TCP and UDP */
202         heur_dissector_add("tcp", dissect_PROTOABBREV, proto_PROTOABBREV);
203         heur_dissector_add("udp", dissect_PROTOABBREV, proto_PROTOABBREV);
204
205         /* register as normal dissector for IP as well */
206         PROTOABBREV_handle = new_create_dissector_handle(dissect_PROTOABBREV,
207             proto_PROTOABBREV);
208         dissector_add_uint("ip.proto", IP_PROTO_PROTOABBREV, PROTOABBREV_handle);
209         PROTOABBREV_inited = TRUE;
210     }
211 }
212