/src/wireshark/epan/packet.c
Line | Count | Source |
1 | | /* packet.c |
2 | | * Routines for packet disassembly |
3 | | * |
4 | | * Wireshark - Network traffic analyzer |
5 | | * By Gerald Combs <gerald@wireshark.org> |
6 | | * Copyright 1998 Gerald Combs |
7 | | * |
8 | | * SPDX-License-Identifier: GPL-2.0-or-later |
9 | | */ |
10 | | |
11 | | #include "config.h" |
12 | 9.50k | #define WS_LOG_DOMAIN LOG_DOMAIN_EPAN |
13 | | |
14 | | #include <glib.h> |
15 | | |
16 | | #include <stdio.h> |
17 | | #include <stdlib.h> |
18 | | |
19 | | #include <stdarg.h> |
20 | | #include <string.h> |
21 | | #include <time.h> |
22 | | |
23 | | #include <epan/packet.h> |
24 | | #include "timestamp.h" |
25 | | |
26 | | #include "osi-utils.h" |
27 | | #include "to_str.h" |
28 | | |
29 | | #include "addr_resolv.h" |
30 | | #include "tvbuff.h" |
31 | | #include "epan_dissect.h" |
32 | | |
33 | | #include <epan/wmem_scopes.h> |
34 | | |
35 | | #include <epan/column-info.h> |
36 | | #include <epan/exceptions.h> |
37 | | #include <epan/reassemble.h> |
38 | | #include <epan/stream.h> |
39 | | #include <epan/expert.h> |
40 | | #include <epan/prefs.h> |
41 | | #include <epan/range.h> |
42 | | |
43 | | #include <wsutil/str_util.h> |
44 | | #include <wsutil/wslog.h> |
45 | | #include <wsutil/ws_assert.h> |
46 | | |
47 | | static int proto_malformed; |
48 | | static dissector_handle_t frame_handle; |
49 | | static dissector_handle_t file_handle; |
50 | | static dissector_handle_t data_handle; |
51 | | |
52 | | /** |
53 | | * A data source. |
54 | | * Has a tvbuff and a name. |
55 | | */ |
56 | | struct data_source { |
57 | | tvbuff_t *tvb; |
58 | | char *name; |
59 | | data_source_media_type_e media_type; |
60 | | }; |
61 | | |
62 | | /* |
63 | | * A dissector table. |
64 | | * |
65 | | * "hash_table" is a hash table, indexed by port number, supplying |
66 | | * a "struct dtbl_entry"; it records what dissector is assigned to |
67 | | * that uint or string value in that table. |
68 | | * |
69 | | * "dissector_handles" is a list of all dissectors that *could* be |
70 | | * used in that table; not all of them are necessarily in the table, |
71 | | * as they may be for protocols that don't have a fixed uint value, |
72 | | * e.g. for TCP or UDP port number tables and protocols with no fixed |
73 | | * port number. It's only non-NULL for tables that allow "Decode As". |
74 | | * After initial handoff registration, it's sorted by the filter name |
75 | | * of the protocol associated with the handle (using an empty string |
76 | | * if there is no protocol.) That's mostly for tshark -d error messages; |
77 | | * the GUI re-sorts by the dissector handle description. (XXX - They |
78 | | * could be sorted on first use, especially if that's the only user.) |
79 | | * |
80 | | * "da_descriptions" is a hash table, keyed by dissector handle description, |
81 | | * of all the dissector handles that could be used for Decode As. The |
82 | | * descriptions are what are presented in the GUI and what are written |
83 | | * to the decode_as_entries UAT. |
84 | | * |
85 | | * "ui_name" is the name the dissector table has in the user interface. |
86 | | * |
87 | | * "type" is a field type giving the width of the uint value for that |
88 | | * dissector table, if it's a uint dissector table. |
89 | | * |
90 | | * "param" is the base in which to display the uint value for that |
91 | | * dissector table, if it's a uint dissector table, or if it's a string |
92 | | * table, true/false to indicate case-insensitive or not. |
93 | | * |
94 | | * "protocol" is the protocol associated with the dissector table. Used |
95 | | * for determining dependencies. |
96 | | */ |
97 | | struct dissector_table { |
98 | | GHashTable *hash_table; |
99 | | GSList *dissector_handles; |
100 | | GHashTable *da_descriptions; |
101 | | const char *ui_name; |
102 | | ftenum_t type; |
103 | | int param; |
104 | | protocol_t *protocol; |
105 | | }; |
106 | | |
107 | | /* |
108 | | * Dissector tables. const char * -> dissector_table * |
109 | | */ |
110 | | static GHashTable *dissector_tables; |
111 | | static bool all_tables_handles_sorted = false; |
112 | | |
113 | | /* |
114 | | * Dissector table aliases. const char * -> const char * |
115 | | */ |
116 | | static GHashTable *dissector_table_aliases; |
117 | | |
118 | | /* |
119 | | * List of registered dissectors. |
120 | | */ |
121 | | static GHashTable *registered_dissectors; |
122 | | |
123 | | /* |
124 | | * A dissector dependency list. |
125 | | * XXX - These are protocol short names, not dissectors (which is likely |
126 | | * what we want, as protocols are enabled and disabled, not dissectors |
127 | | * other than heuristic dissectors.) |
128 | | */ |
129 | | struct depend_dissector_list { |
130 | | GHashTable *dissectors; |
131 | | }; |
132 | | |
133 | | /* Maps char * protocol short name to depend_dissector_list_t |
134 | | * XXX - This doesn't get freed when proto_deregister_dissector |
135 | | * is called. Might it make sense to store this information in |
136 | | * the proto_t? |
137 | | * XXX - Which direction should these be stored? Issue #1402 discusses, |
138 | | * e.g., if HTTP is enabled then making sure that lower level protocols |
139 | | * like TLS, TCP, IP, etc. are enabled. But here as registered the key |
140 | | * is the protocol of the dissector that calls the other handle (whether |
141 | | * via table or registered with _add_dependency.) That is, "TCP" and |
142 | | * "TLS" are keys that have "HTTP" in their depend_dissector_list, rather |
143 | | * than the other way around. Either use could be interesting (a bit moot |
144 | | * since this isn't actually used yet.) |
145 | | */ |
146 | | static GHashTable *depend_dissector_lists; |
147 | | |
148 | | /* Allow protocols to register a "cleanup" routine to be |
149 | | * run after the initial sequential run through the packets. |
150 | | * Note that the file can still be open after this; this is not |
151 | | * the final cleanup. */ |
152 | | static GSList *postseq_cleanup_routines; |
153 | | |
154 | | /* |
155 | | * Post-dissector information - handle for the dissector and a list |
156 | | * of hfids for the fields the post-dissector wants. |
157 | | */ |
158 | | typedef struct { |
159 | | dissector_handle_t handle; |
160 | | GArray *wanted_hfids; |
161 | | } postdissector; |
162 | | |
163 | | /* |
164 | | * Array of all postdissectors. |
165 | | */ |
166 | | static GArray *postdissectors; |
167 | | |
168 | | /* |
169 | | * i-th element of that array. |
170 | | */ |
171 | 2.29M | #define POSTDISSECTORS(i) g_array_index(postdissectors, postdissector, i) |
172 | | |
173 | | static void |
174 | | destroy_depend_dissector_list(void *data) |
175 | 0 | { |
176 | 0 | depend_dissector_list_t dissector_list = (depend_dissector_list_t)data; |
177 | 0 | GHashTable *table = dissector_list->dissectors; |
178 | |
|
179 | 0 | g_hash_table_destroy(table); |
180 | 0 | g_slice_free(struct depend_dissector_list, dissector_list); |
181 | 0 | } |
182 | | |
183 | | /* |
184 | | * A heuristics dissector list. |
185 | | */ |
186 | | struct heur_dissector_list { |
187 | | const char *ui_name; |
188 | | protocol_t *protocol; |
189 | | GSList *dissectors; |
190 | | }; |
191 | | |
192 | | static GHashTable *heur_dissector_lists; |
193 | | |
194 | | /* Name hashtables for fast detection of duplicate names */ |
195 | | static GHashTable* heuristic_short_names; |
196 | | |
197 | | static void |
198 | | destroy_heuristic_dissector_entry(void *data) |
199 | 0 | { |
200 | 0 | heur_dtbl_entry_t *hdtbl_entry = (heur_dtbl_entry_t *)data; |
201 | 0 | g_free(hdtbl_entry->list_name); |
202 | 0 | g_free(hdtbl_entry->short_name); |
203 | 0 | g_slice_free(heur_dtbl_entry_t, data); |
204 | 0 | } |
205 | | |
206 | | static void |
207 | | destroy_heuristic_dissector_list(void *data) |
208 | 0 | { |
209 | 0 | heur_dissector_list_t dissector_list = (heur_dissector_list_t)data; |
210 | 0 | GSList **list = &(dissector_list->dissectors); |
211 | |
|
212 | 0 | g_slist_free_full(*list, destroy_heuristic_dissector_entry); |
213 | 0 | g_slice_free(struct heur_dissector_list, dissector_list); |
214 | 0 | } |
215 | | |
216 | | static void |
217 | | destroy_dissector_table(void *data) |
218 | 0 | { |
219 | 0 | struct dissector_table *table = (struct dissector_table *)data; |
220 | |
|
221 | 0 | g_hash_table_destroy(table->hash_table); |
222 | 0 | g_slist_free(table->dissector_handles); |
223 | 0 | if (table->da_descriptions) |
224 | 0 | g_hash_table_destroy(table->da_descriptions); |
225 | 0 | g_slice_free(struct dissector_table, data); |
226 | 0 | } |
227 | | |
228 | | void |
229 | | packet_init(void) |
230 | 16 | { |
231 | 16 | dissector_tables = g_hash_table_new_full(g_str_hash, g_str_equal, |
232 | 16 | NULL, destroy_dissector_table); |
233 | 16 | all_tables_handles_sorted = false; |
234 | | |
235 | 16 | dissector_table_aliases = g_hash_table_new_full(g_str_hash, g_str_equal, |
236 | 16 | NULL, NULL); |
237 | | |
238 | 16 | registered_dissectors = g_hash_table_new_full(g_str_hash, g_str_equal, |
239 | 16 | NULL, NULL); |
240 | | |
241 | 16 | postdissectors = g_array_sized_new(false, false, (unsigned)sizeof(postdissector), 1); |
242 | | |
243 | 16 | depend_dissector_lists = g_hash_table_new_full(g_str_hash, g_str_equal, |
244 | 16 | g_free, destroy_depend_dissector_list); |
245 | | |
246 | 16 | heur_dissector_lists = g_hash_table_new_full(g_str_hash, g_str_equal, |
247 | 16 | NULL, destroy_heuristic_dissector_list); |
248 | | |
249 | 16 | heuristic_short_names = g_hash_table_new(g_str_hash, g_str_equal); |
250 | 16 | } |
251 | | |
252 | | void |
253 | | packet_cache_proto_handles(void) |
254 | 16 | { |
255 | 16 | frame_handle = find_dissector("frame"); |
256 | 16 | ws_assert(frame_handle != NULL); |
257 | | |
258 | 16 | file_handle = find_dissector("file"); |
259 | 16 | ws_assert(file_handle != NULL); |
260 | | |
261 | 16 | data_handle = find_dissector("data"); |
262 | 16 | ws_assert(data_handle != NULL); |
263 | | |
264 | 16 | proto_malformed = proto_get_id_by_filter_name("_ws.malformed"); |
265 | 16 | ws_assert(proto_malformed != -1); |
266 | 16 | } |
267 | | |
268 | | /* List of routines that are called before we make a pass through a capture file |
269 | | * and dissect all its packets. See register_init_routine, register_cleanup_routine |
270 | | * and register_shutdown_routine in packet.h */ |
271 | | /** |
272 | | * List of "init" routines, which are called before we make a pass through |
273 | | * a capture file and dissect all its packets (e.g., when we read in a |
274 | | * new capture file, or run a "filter packets" or "colorize packets" |
275 | | * pass over the current capture file or when the preferences are changed). |
276 | | * |
277 | | * See register_init_routine(). |
278 | | */ |
279 | | static GSList *init_routines; |
280 | | |
281 | | /** |
282 | | * List of "cleanup" routines, which are called after closing a capture |
283 | | * file (or when preferences are changed; in that case these routines |
284 | | * are called before the init routines are executed). They can be used |
285 | | * to release resources that are allocated in an "init" routine. |
286 | | * |
287 | | * See register_cleanup_routine(). |
288 | | */ |
289 | | static GSList *cleanup_routines; |
290 | | |
291 | | /* |
292 | | * List of "shutdown" routines, which are called once, just before |
293 | | * program exit. |
294 | | * |
295 | | * See register_shutdown_routine(). |
296 | | */ |
297 | | static GSList *shutdown_routines; |
298 | | |
299 | | typedef void (*void_func_t)(void); |
300 | | |
301 | | /* Initialize all data structures used for dissection. */ |
302 | | static void |
303 | | call_routine(void *routine, void *dummy _U_) |
304 | 1.55k | { |
305 | 1.55k | void_func_t func = (void_func_t)routine; |
306 | 1.55k | (*func)(); |
307 | 1.55k | } |
308 | | |
309 | | void |
310 | | packet_cleanup(void) |
311 | 0 | { |
312 | 0 | g_slist_free(init_routines); |
313 | 0 | g_slist_free(cleanup_routines); |
314 | 0 | g_slist_free(postseq_cleanup_routines); |
315 | 0 | g_hash_table_destroy(dissector_tables); |
316 | 0 | g_hash_table_destroy(dissector_table_aliases); |
317 | 0 | g_hash_table_destroy(registered_dissectors); |
318 | 0 | g_hash_table_destroy(depend_dissector_lists); |
319 | 0 | g_hash_table_destroy(heur_dissector_lists); |
320 | 0 | g_hash_table_destroy(heuristic_short_names); |
321 | 0 | g_slist_foreach(shutdown_routines, &call_routine, NULL); |
322 | 0 | g_slist_free(shutdown_routines); |
323 | 0 | if (postdissectors) { |
324 | 0 | for (unsigned i = 0; i < postdissectors->len; i++) { |
325 | 0 | if (POSTDISSECTORS(i).wanted_hfids) { |
326 | 0 | g_array_free(POSTDISSECTORS(i).wanted_hfids, true); |
327 | 0 | } |
328 | 0 | } |
329 | 0 | g_array_free(postdissectors, true); |
330 | 0 | } |
331 | 0 | } |
332 | | |
333 | | /* |
334 | | * Given a tvbuff, and a length from a packet header, adjust the length |
335 | | * of the tvbuff to reflect the specified length. |
336 | | */ |
337 | | void |
338 | | set_actual_length(tvbuff_t *tvb, const unsigned specified_len) |
339 | 33.7k | { |
340 | 33.7k | if (specified_len < tvb_reported_length(tvb)) { |
341 | | /* Adjust the length of this tvbuff to include only the specified |
342 | | payload length. |
343 | | |
344 | | The dissector above the one calling us (the dissector above is |
345 | | probably us) may use that to determine how much of its packet |
346 | | was padding. */ |
347 | 984 | tvb_set_reported_length(tvb, specified_len); |
348 | 984 | } |
349 | 33.7k | } |
350 | | |
351 | | void |
352 | | register_init_routine(void (*func)(void)) |
353 | 1.55k | { |
354 | 1.55k | init_routines = g_slist_prepend(init_routines, (void *)func); |
355 | 1.55k | } |
356 | | |
357 | | void |
358 | | register_cleanup_routine(void (*func)(void)) |
359 | 848 | { |
360 | 848 | cleanup_routines = g_slist_prepend(cleanup_routines, (void *)func); |
361 | 848 | } |
362 | | |
363 | | /* register a new shutdown routine */ |
364 | | void |
365 | | register_shutdown_routine(void (*func)(void)) |
366 | 418 | { |
367 | 418 | shutdown_routines = g_slist_prepend(shutdown_routines, (void *)func); |
368 | 418 | } |
369 | | |
370 | | /* Initialize all data structures used for dissection. */ |
371 | | void |
372 | | init_dissection(const char* app_env_var_prefix) |
373 | 16 | { |
374 | | /* |
375 | | * Reinitialize resolution information. Don't leak host entries from |
376 | | * one file to another (e.g. embarrassing-host-name.example.com from |
377 | | * file1.pcapng into a name resolution block in file2.pcapng). |
378 | | */ |
379 | 16 | host_name_lookup_reset(app_env_var_prefix); |
380 | | |
381 | 16 | wmem_enter_file_scope(); |
382 | | |
383 | | /* Initialize the table of conversations. */ |
384 | 16 | epan_conversation_init(); |
385 | | |
386 | | /* Initialize protocol-specific variables. */ |
387 | 16 | g_slist_foreach(init_routines, &call_routine, NULL); |
388 | | |
389 | | /* Initialize the stream-handling tables */ |
390 | 16 | stream_init(); |
391 | | |
392 | | /* Initialize the expert infos */ |
393 | 16 | expert_packet_init(); |
394 | 16 | } |
395 | | |
396 | | void |
397 | | cleanup_dissection(void) |
398 | 0 | { |
399 | | /* Cleanup protocol-specific variables. */ |
400 | 0 | g_slist_foreach(cleanup_routines, &call_routine, NULL); |
401 | | |
402 | | /* Cleanup the stream-handling tables */ |
403 | 0 | stream_cleanup(); |
404 | | |
405 | | /* Cleanup the expert infos */ |
406 | 0 | expert_packet_cleanup(); |
407 | |
|
408 | 0 | wmem_leave_file_scope(); |
409 | | |
410 | | /* |
411 | | * Keep the name resolution info around until we start the next |
412 | | * dissection. Lua scripts may potentially do name resolution at |
413 | | * any time, even if we're not dissecting and have no capture |
414 | | * file open. |
415 | | */ |
416 | 0 | } |
417 | | |
418 | | void |
419 | | register_postseq_cleanup_routine(void_func_t func) |
420 | 16 | { |
421 | 16 | postseq_cleanup_routines = g_slist_prepend(postseq_cleanup_routines, |
422 | 16 | (void *)func); |
423 | 16 | } |
424 | | |
425 | | /* Call all the registered "postseq_cleanup" routines. */ |
426 | | void |
427 | | postseq_cleanup_all_protocols(void) |
428 | 0 | { |
429 | 0 | g_slist_foreach(postseq_cleanup_routines, |
430 | 0 | &call_routine, NULL); |
431 | 0 | } |
432 | | |
433 | | /* |
434 | | * Add a new data source to the list of data sources for a frame, given |
435 | | * the tvbuff for the data source and its name. |
436 | | */ |
437 | | struct data_source *add_new_data_source(packet_info *pinfo, tvbuff_t *tvb, const char *name) |
438 | 650k | { |
439 | 650k | struct data_source *src; |
440 | | |
441 | 650k | src = wmem_new(pinfo->pool, struct data_source); |
442 | 650k | src->tvb = tvb; |
443 | 650k | src->name = wmem_strdup(pinfo->pool, name); |
444 | 650k | src->media_type = DS_MEDIA_TYPE_APPLICATION_OCTET_STREAM; |
445 | | /* This could end up slow, but we should never have that many data |
446 | | * sources so it probably doesn't matter */ |
447 | 650k | pinfo->data_src = g_slist_append(pinfo->data_src, src); |
448 | 650k | return src; |
449 | 650k | } |
450 | | |
451 | | void |
452 | | set_data_source_name(packet_info *pinfo, struct data_source *src, const char *name) |
453 | 0 | { |
454 | 0 | if (src) { |
455 | 0 | src->name = wmem_strdup(pinfo->pool, name); |
456 | 0 | } |
457 | 0 | } |
458 | | |
459 | | void set_data_source_media_type(struct data_source *src, data_source_media_type_e media_type) |
460 | 0 | { |
461 | 0 | if (src) { |
462 | 0 | src->media_type = media_type; |
463 | 0 | } |
464 | 0 | } |
465 | | |
466 | | void |
467 | | remove_last_data_source(packet_info *pinfo) |
468 | 0 | { |
469 | 0 | GSList *last; |
470 | |
|
471 | 0 | last = g_slist_last(pinfo->data_src); |
472 | 0 | pinfo->data_src = g_slist_delete_link(pinfo->data_src, last); |
473 | 0 | } |
474 | | |
475 | | char* |
476 | | get_data_source_description(const struct data_source *src) |
477 | 0 | { |
478 | 0 | unsigned length = tvb_captured_length(src->tvb); |
479 | |
|
480 | 0 | return wmem_strdup_printf(NULL, "%s (%u byte%s)", src->name, length, |
481 | 0 | plurality(length, "", "s")); |
482 | 0 | } |
483 | | |
484 | | const char * |
485 | | get_data_source_name(const struct data_source *src) |
486 | 0 | { |
487 | 0 | if (src) { |
488 | 0 | return src->name; |
489 | 0 | } |
490 | 0 | return NULL; |
491 | 0 | } |
492 | | |
493 | | tvbuff_t * |
494 | | get_data_source_tvb(const struct data_source *src) |
495 | 0 | { |
496 | 0 | if (src) { |
497 | 0 | return src->tvb; |
498 | 0 | } |
499 | 0 | return NULL; |
500 | 0 | } |
501 | | |
502 | | /* |
503 | | * Find and return data source with the given name. |
504 | | */ |
505 | | struct data_source * |
506 | | get_data_source_by_name(const packet_info *pinfo, const char *name) |
507 | 0 | { |
508 | 0 | if (!pinfo) { |
509 | 0 | return NULL; |
510 | 0 | } |
511 | 0 | for (GSList *source = pinfo->data_src; source; source = source->next) { |
512 | 0 | struct data_source *this_source = (struct data_source *)source->data; |
513 | 0 | if (this_source->name && strcmp(this_source->name, name) == 0) { |
514 | 0 | return this_source; |
515 | 0 | } |
516 | 0 | } |
517 | 0 | return NULL; |
518 | 0 | } |
519 | | |
520 | | /* |
521 | | * Find and return the data source associated with a given tvb. |
522 | | */ |
523 | | struct data_source * |
524 | | get_data_source_by_tvb(const packet_info *pinfo, const tvbuff_t *tvb) |
525 | 0 | { |
526 | 0 | if (!pinfo) { |
527 | 0 | return NULL; |
528 | 0 | } |
529 | 0 | for (GSList *source = pinfo->data_src; source; source = source->next) { |
530 | 0 | struct data_source *this_source = (struct data_source *)source->data; |
531 | 0 | if (this_source->tvb == tvb) { |
532 | 0 | return this_source; |
533 | 0 | } |
534 | 0 | } |
535 | 0 | return NULL; |
536 | 0 | } |
537 | | |
538 | | int32_t get_data_source_index_by_tvb(const packet_info *pinfo, const tvbuff_t *tvb) |
539 | 6.26k | { |
540 | 6.26k | if (!pinfo) { |
541 | 0 | return -1; |
542 | 0 | } |
543 | 6.26k | int32_t idx = 0; |
544 | 6.86k | for (GSList *source = pinfo->data_src; source; source = source->next) { |
545 | 6.86k | struct data_source *this_source = (struct data_source *)source->data; |
546 | 6.86k | if (this_source->tvb == tvb) { |
547 | 6.26k | return idx; |
548 | 6.26k | } |
549 | 594 | ++idx; |
550 | 594 | } |
551 | 0 | return -1; |
552 | 6.26k | } |
553 | | |
554 | | data_source_media_type_e get_data_source_media_type(const struct data_source *src) |
555 | 0 | { |
556 | 0 | if (src) { |
557 | 0 | return src->media_type; |
558 | 0 | } |
559 | 0 | return DS_MEDIA_TYPE_APPLICATION_OCTET_STREAM; |
560 | 0 | } |
561 | | |
562 | | |
563 | | /* |
564 | | * Free up a frame's list of data sources. |
565 | | */ |
566 | | void |
567 | | free_data_sources(packet_info *pinfo) |
568 | 191k | { |
569 | 191k | if (pinfo->data_src) { |
570 | 191k | g_slist_free(pinfo->data_src); |
571 | 191k | pinfo->data_src = NULL; |
572 | 191k | } |
573 | 191k | } |
574 | | |
575 | | void |
576 | | mark_frame_as_depended_upon(frame_data *fd, uint32_t frame_num) |
577 | 20.2k | { |
578 | | /* Don't mark a frame as dependent on itself */ |
579 | 20.2k | if (frame_num != fd->num) { |
580 | | /* ws_assert(frame_num < fd->num) - we assume in several other |
581 | | * places in the code that frames don't depend on future |
582 | | * frames. */ |
583 | 2.96k | if (fd->dependent_frames == NULL) { |
584 | 672 | fd->dependent_frames = g_hash_table_new(g_direct_hash, g_direct_equal); |
585 | 672 | } |
586 | 2.96k | g_hash_table_add(fd->dependent_frames, GUINT_TO_POINTER(frame_num)); |
587 | 2.96k | } |
588 | 20.2k | } |
589 | | |
590 | | /* Allow dissectors to register a "final_registration" routine |
591 | | * that is run like the proto_register_XXX() routine, but at the |
592 | | * end of the epan_init() function; that is, *after* all other |
593 | | * subsystems, like dfilters, have finished initializing. This is |
594 | | * useful for dissector registration routines which need to compile |
595 | | * display filters. dfilters can't initialize itself until all protocols |
596 | | * have registered themselves. */ |
597 | | static GSList *final_registration_routines; |
598 | | |
599 | | void |
600 | | register_final_registration_routine(void (*func)(void)) |
601 | 0 | { |
602 | 0 | final_registration_routines = g_slist_prepend(final_registration_routines, |
603 | 0 | (void *)func); |
604 | 0 | } |
605 | | |
606 | | /* Call all the registered "final_registration" routines. */ |
607 | | void |
608 | | final_registration_all_protocols(void) |
609 | 16 | { |
610 | 16 | g_slist_foreach(final_registration_routines, |
611 | 16 | &call_routine, NULL); |
612 | 16 | } |
613 | | |
614 | | |
615 | | /* Creates the top-most tvbuff and calls the "frame" dissector */ |
616 | | void |
617 | | dissect_record(epan_dissect_t *edt, int file_type_subtype, wtap_rec *rec, |
618 | | frame_data *fd, column_info *cinfo) |
619 | 191k | { |
620 | 191k | frame_data_t frame_dissector_data; |
621 | | |
622 | 191k | if (!fd->visited) { |
623 | | /* This is the first pass, so prime the epan_dissect_t with the |
624 | | hfids postdissectors want on the first pass. */ |
625 | | /* XXX - This can fail with an unhandled exception, e.g., if a |
626 | | * field was deregistered. */ |
627 | 191k | prime_epan_dissect_with_postdissector_wanted_hfids(edt); |
628 | 191k | } |
629 | | |
630 | 191k | if (cinfo != NULL) |
631 | 0 | col_init(cinfo, edt->session); |
632 | 191k | edt->pi.epan = edt->session; |
633 | | /* edt->pi.pool created in epan_dissect_init() */ |
634 | 191k | edt->pi.current_proto = "<Missing Protocol Name>"; |
635 | 191k | edt->pi.cinfo = cinfo; |
636 | 191k | edt->pi.presence_flags = 0; |
637 | 191k | edt->pi.num = fd->num; |
638 | | /* |
639 | | * XXX - this doesn't check the wtap_rec because, for |
640 | | * some capture files, time stamps are supplied only |
641 | | * when reading sequentially, so we keep the time stamp |
642 | | * in the frame_data structure. |
643 | | */ |
644 | 191k | if (fd->has_ts) { |
645 | 191k | edt->pi.presence_flags |= PINFO_HAS_TS; |
646 | 191k | edt->pi.abs_ts = fd->abs_ts; |
647 | 191k | } |
648 | 191k | switch (rec->rec_type) { |
649 | | |
650 | 191k | case REC_TYPE_PACKET: |
651 | 191k | edt->pi.pseudo_header = &rec->rec_header.packet_header.pseudo_header; |
652 | 191k | break; |
653 | | |
654 | 0 | case REC_TYPE_FT_SPECIFIC_EVENT: |
655 | 0 | case REC_TYPE_FT_SPECIFIC_REPORT: |
656 | 0 | edt->pi.pseudo_header = &rec->rec_header.ft_specific_header.pseudo_header; |
657 | 0 | break; |
658 | | |
659 | 0 | case REC_TYPE_SYSCALL: |
660 | 0 | edt->pi.pseudo_header = NULL; |
661 | 0 | break; |
662 | | |
663 | 0 | case REC_TYPE_SYSTEMD_JOURNAL_EXPORT: |
664 | 0 | edt->pi.pseudo_header = NULL; |
665 | 0 | break; |
666 | | |
667 | 0 | case REC_TYPE_CUSTOM_BLOCK: |
668 | 0 | edt->pi.pseudo_header = NULL; |
669 | 0 | break; |
670 | | |
671 | 191k | } |
672 | | |
673 | 191k | edt->pi.fd = fd; |
674 | 191k | edt->pi.rec = rec; |
675 | 191k | clear_address(&edt->pi.dl_src); |
676 | 191k | clear_address(&edt->pi.dl_dst); |
677 | 191k | clear_address(&edt->pi.net_src); |
678 | 191k | clear_address(&edt->pi.net_dst); |
679 | 191k | clear_address(&edt->pi.src); |
680 | 191k | clear_address(&edt->pi.dst); |
681 | 191k | edt->pi.noreassembly_reason = ""; |
682 | 191k | edt->pi.ptype = PT_NONE; |
683 | 191k | edt->pi.use_conv_addr_port_endpoints = false; |
684 | 191k | edt->pi.conv_addr_port_endpoints = NULL; |
685 | 191k | edt->pi.conv_elements = NULL; |
686 | 191k | edt->pi.p2p_dir = P2P_DIR_UNKNOWN; |
687 | 191k | edt->pi.link_dir = LINK_DIR_UNKNOWN; |
688 | 191k | edt->pi.src_win_scale = -1; /* unknown Rcv.Wind.Shift */ |
689 | 191k | edt->pi.dst_win_scale = -1; /* unknown Rcv.Wind.Shift */ |
690 | 191k | edt->pi.layers = wmem_list_new(edt->pi.pool); |
691 | 191k | edt->pi.proto_data = NULL; |
692 | 191k | edt->tvb = NULL; |
693 | | |
694 | | /* |
695 | | * This is time relative to the first frame in the capture, |
696 | | * regardless of what time reference frames precede it. |
697 | | * |
698 | | * XXX - should there be a field indicating whether the |
699 | | * frame *has* a relative time stamp? |
700 | | * |
701 | | * XXX - what is pinfo->rel_ts used for? All times are |
702 | | * relative to some zero point on the t axis, so why |
703 | | * is pinfo->rel_ts used instead of pinfo->abs_ts? |
704 | | * |
705 | | * XXX - Some records aren't packets, and some, packets or not, don't |
706 | | * have time stamps. Should pinfo->rel_ts be relative to the first |
707 | | * frame (or packet record, or record of the time type as the current |
708 | | * record?) that *has* a time stamp? |
709 | | */ |
710 | 191k | frame_rel_first_frame_time(edt->session, fd, &edt->pi.rel_ts); |
711 | | |
712 | | /* pinfo->rel_cap_ts is used by the new Plot dialog, though |
713 | | * it could probably just use frame_rel_start_time instead. |
714 | | */ |
715 | 191k | nstime_t rel_time; |
716 | 191k | if (frame_rel_start_time(edt->session, fd, &rel_time)) { |
717 | 0 | nstime_copy(&edt->pi.rel_cap_ts, &rel_time); |
718 | 0 | edt->pi.rel_cap_ts_present = true; |
719 | 0 | } |
720 | | |
721 | | /* |
722 | | * If the block has been modified, use the modified block, |
723 | | * otherwise use the block from the file. |
724 | | */ |
725 | 191k | if (fd->has_modified_block) { |
726 | 0 | frame_dissector_data.pkt_block = epan_get_modified_block(edt->session, fd); |
727 | 0 | } |
728 | 191k | else { |
729 | 191k | frame_dissector_data.pkt_block = rec->block; |
730 | 191k | } |
731 | 191k | frame_dissector_data.file_type_subtype = file_type_subtype; |
732 | 191k | frame_dissector_data.color_edt = edt; /* Used strictly for "coloring rules" */ |
733 | | |
734 | 191k | TRY { |
735 | | /* |
736 | | * XXX - currently, the length arguments in |
737 | | * tvbuff structure are signed, but the captured |
738 | | * and reported length values are unsigned; this means |
739 | | * that length values > 2^31 - 1 will appear as |
740 | | * negative lengths |
741 | | * |
742 | | * Captured length values that large will already |
743 | | * have been filtered out by the Wiretap modules |
744 | | * (the file will be reported as corrupted), to |
745 | | * avoid trying to allocate large chunks of data. |
746 | | * |
747 | | * Reported length values will not have been |
748 | | * filtered out, and should not be filtered out, |
749 | | * as those lengths are not necessarily invalid. |
750 | | */ |
751 | 191k | edt->tvb = tvb_new_real_data(ws_buffer_start_ptr(&rec->data), |
752 | 191k | fd->cap_len, fd->pkt_len); |
753 | | /* Add this tvbuffer into the data_src list */ |
754 | 191k | add_new_data_source(&edt->pi, edt->tvb, rec->rec_type_name); |
755 | | |
756 | | /* Even though dissect_frame() catches all the exceptions a |
757 | | * sub-dissector can throw, dissect_frame() itself may throw |
758 | | * a ReportedBoundsError in bizarre cases. Thus, we catch the exception |
759 | | * in this function. */ |
760 | 191k | call_dissector_with_data(frame_handle, edt->tvb, &edt->pi, edt->tree, &frame_dissector_data); |
761 | 191k | } |
762 | 191k | CATCH(BoundsError) { |
763 | 0 | ws_assert_not_reached(); |
764 | 0 | } |
765 | 191k | CATCH2(FragmentBoundsError, ReportedBoundsError) { |
766 | 0 | proto_tree_add_protocol_format(edt->tree, proto_malformed, edt->tvb, 0, 0, |
767 | 0 | "[Malformed %s: Packet Length]", |
768 | 0 | rec->rec_type_name); |
769 | 0 | } |
770 | 191k | ENDTRY; |
771 | 191k | wtap_block_unref(rec->block); |
772 | 191k | rec->block = NULL; |
773 | | |
774 | 191k | fd->visited = 1; |
775 | 191k | } |
776 | | |
777 | | /* Creates the top-most tvbuff and calls the "file" dissector */ |
778 | | void |
779 | | dissect_file(epan_dissect_t *edt, wtap_rec *rec, |
780 | | frame_data *fd, column_info *cinfo) |
781 | 0 | { |
782 | 0 | file_data_t file_dissector_data; |
783 | |
|
784 | 0 | if (!fd->visited) { |
785 | | /* This is the first pass, so prime the epan_dissect_t with the |
786 | | hfids postdissectors want on the first pass. */ |
787 | 0 | prime_epan_dissect_with_postdissector_wanted_hfids(edt); |
788 | 0 | } |
789 | |
|
790 | 0 | if (cinfo != NULL) |
791 | 0 | col_init(cinfo, edt->session); |
792 | 0 | edt->pi.epan = edt->session; |
793 | | /* edt->pi.pool created in epan_dissect_init() */ |
794 | 0 | edt->pi.current_proto = "<Missing Filetype Name>"; |
795 | 0 | edt->pi.cinfo = cinfo; |
796 | 0 | edt->pi.fd = fd; |
797 | 0 | edt->pi.rec = rec; |
798 | 0 | edt->pi.pseudo_header = NULL; |
799 | 0 | clear_address(&edt->pi.dl_src); |
800 | 0 | clear_address(&edt->pi.dl_dst); |
801 | 0 | clear_address(&edt->pi.net_src); |
802 | 0 | clear_address(&edt->pi.net_dst); |
803 | 0 | clear_address(&edt->pi.src); |
804 | 0 | clear_address(&edt->pi.dst); |
805 | 0 | edt->pi.noreassembly_reason = ""; |
806 | 0 | edt->pi.ptype = PT_NONE; |
807 | 0 | edt->pi.use_conv_addr_port_endpoints = false; |
808 | 0 | edt->pi.conv_addr_port_endpoints = NULL; |
809 | 0 | edt->pi.conv_elements = NULL; |
810 | 0 | edt->pi.p2p_dir = P2P_DIR_UNKNOWN; |
811 | 0 | edt->pi.link_dir = LINK_DIR_UNKNOWN; |
812 | 0 | edt->pi.layers = wmem_list_new(edt->pi.pool); |
813 | 0 | edt->pi.proto_data = NULL; |
814 | 0 | edt->tvb = NULL; |
815 | |
|
816 | 0 | frame_rel_first_frame_time(edt->session, fd, &edt->pi.rel_ts); |
817 | |
|
818 | 0 | TRY { |
819 | | /* |
820 | | * If the block has been modified, use the modified block, |
821 | | * otherwise use the block from the file. |
822 | | */ |
823 | 0 | if (fd->has_modified_block) { |
824 | 0 | file_dissector_data.pkt_block = epan_get_modified_block(edt->session, fd); |
825 | 0 | } |
826 | 0 | else { |
827 | 0 | file_dissector_data.pkt_block = rec->block; |
828 | 0 | } |
829 | 0 | file_dissector_data.color_edt = edt; /* Used strictly for "coloring rules" */ |
830 | |
|
831 | 0 | edt->tvb = tvb_new_real_data(ws_buffer_start_ptr(&rec->data), |
832 | 0 | fd->cap_len, fd->pkt_len > INT_MAX ? INT_MAX : fd->pkt_len); |
833 | | /* Add this tvbuffer into the data_src list */ |
834 | 0 | add_new_data_source(&edt->pi, edt->tvb, "File"); |
835 | | |
836 | | /* Even though dissect_file() catches all the exceptions a |
837 | | * sub-dissector can throw, dissect_frame() itself may throw |
838 | | * a ReportedBoundsError in bizarre cases. Thus, we catch the exception |
839 | | * in this function. */ |
840 | 0 | call_dissector_with_data(file_handle, edt->tvb, &edt->pi, edt->tree, &file_dissector_data); |
841 | |
|
842 | 0 | } |
843 | 0 | CATCH(BoundsError) { |
844 | 0 | ws_assert_not_reached(); |
845 | 0 | } |
846 | 0 | CATCH3(FragmentBoundsError, ContainedBoundsError, ReportedBoundsError) { |
847 | 0 | proto_tree_add_protocol_format(edt->tree, proto_malformed, edt->tvb, 0, 0, |
848 | 0 | "[Malformed Record: Packet Length]"); |
849 | 0 | } |
850 | 0 | ENDTRY; |
851 | 0 | wtap_block_unref(rec->block); |
852 | 0 | rec->block = NULL; |
853 | |
|
854 | 0 | fd->visited = 1; |
855 | 0 | } |
856 | | |
857 | | /*********************** code added for sub-dissector lookup *********************/ |
858 | | |
859 | | enum dissector_e { |
860 | | DISSECTOR_TYPE_SIMPLE, |
861 | | DISSECTOR_TYPE_CALLBACK |
862 | | }; |
863 | | |
864 | | /* |
865 | | * A dissector handle. |
866 | | */ |
867 | | struct dissector_handle { |
868 | | const char *name; /* dissector name */ |
869 | | const char *description; /* dissector description */ |
870 | | char *pref_suffix; |
871 | | enum dissector_e dissector_type; |
872 | | union { |
873 | | dissector_t dissector_type_simple; |
874 | | dissector_cb_t dissector_type_callback; |
875 | | } dissector_func; |
876 | | void *dissector_data; |
877 | | protocol_t *protocol; |
878 | | }; |
879 | | |
880 | | static void |
881 | | add_layer(packet_info *pinfo, int proto_id) |
882 | 1.79M | { |
883 | 1.79M | int *proto_layer_num_ptr; |
884 | | |
885 | 1.79M | pinfo->curr_layer_num++; |
886 | 1.79M | wmem_list_append(pinfo->layers, GINT_TO_POINTER(proto_id)); |
887 | | |
888 | | /* Increment layer number for this proto id. */ |
889 | 1.79M | if (pinfo->proto_layers == NULL) { |
890 | 191k | pinfo->proto_layers = wmem_map_new(pinfo->pool, g_direct_hash, g_direct_equal); |
891 | 191k | } |
892 | | |
893 | 1.79M | proto_layer_num_ptr = wmem_map_lookup(pinfo->proto_layers, GINT_TO_POINTER(proto_id)); |
894 | 1.79M | if (proto_layer_num_ptr == NULL) { |
895 | | /* Insert new layer */ |
896 | 1.34M | proto_layer_num_ptr = wmem_new(pinfo->pool, int); |
897 | 1.34M | *proto_layer_num_ptr = 1; |
898 | 1.34M | wmem_map_insert(pinfo->proto_layers, GINT_TO_POINTER(proto_id), proto_layer_num_ptr); |
899 | 1.34M | } |
900 | 446k | else { |
901 | | /* Increment layer number */ |
902 | 446k | (*proto_layer_num_ptr)++; |
903 | 446k | } |
904 | 1.79M | pinfo->curr_proto_layer_num = *proto_layer_num_ptr; |
905 | 1.79M | } |
906 | | |
907 | | static void |
908 | | remove_last_layer(packet_info *pinfo, bool reduce_count) |
909 | 453k | { |
910 | 453k | int *proto_layer_num_ptr; |
911 | 453k | wmem_list_frame_t *frame; |
912 | 453k | int proto_id; |
913 | | |
914 | 453k | if (reduce_count) { |
915 | 451k | pinfo->curr_layer_num--; |
916 | 451k | } |
917 | | |
918 | 453k | frame = wmem_list_tail(pinfo->layers); |
919 | 453k | proto_id = GPOINTER_TO_INT(wmem_list_frame_data(frame)); |
920 | 453k | wmem_list_remove_frame(pinfo->layers, frame); |
921 | | |
922 | 453k | if (reduce_count) { |
923 | | /* Reduce count for removed protocol layer. */ |
924 | 451k | proto_layer_num_ptr = wmem_map_lookup(pinfo->proto_layers, GINT_TO_POINTER(proto_id)); |
925 | 451k | if (proto_layer_num_ptr && *proto_layer_num_ptr > 0) { |
926 | 451k | (*proto_layer_num_ptr)--; |
927 | 451k | } |
928 | 451k | } |
929 | 453k | } |
930 | | |
931 | | |
932 | | /* This function will return |
933 | | * >0 this protocol was successfully dissected and this was this protocol. |
934 | | * 0 this packet did not match this protocol. |
935 | | * |
936 | | * XXX - if the dissector only dissects metadata passed through the data |
937 | | * pointer, and dissects none of the packet data, that's indistinguishable |
938 | | * from "packet did not match this protocol". See issues #12366 and |
939 | | * #12368. |
940 | | */ |
941 | | static int |
942 | | call_dissector_through_handle(dissector_handle_t handle, tvbuff_t *tvb, |
943 | | packet_info *pinfo, proto_tree *tree, void *data) |
944 | 1.62M | { |
945 | 1.62M | const char *saved_proto; |
946 | 1.62M | int saved_proto_layer_num; |
947 | 1.62M | int len; |
948 | | |
949 | 1.62M | saved_proto = pinfo->current_proto; |
950 | 1.62M | saved_proto_layer_num = pinfo->curr_proto_layer_num; |
951 | | |
952 | 1.62M | if ((handle->protocol != NULL) && (!proto_is_bytes_pino(handle->protocol))) { |
953 | 1.54M | pinfo->current_proto = |
954 | 1.54M | proto_get_protocol_short_name(handle->protocol); |
955 | 1.54M | } |
956 | | |
957 | 1.62M | switch (handle->dissector_type) { |
958 | | |
959 | 1.62M | case DISSECTOR_TYPE_SIMPLE: |
960 | 1.62M | len = (handle->dissector_func.dissector_type_simple)(tvb, pinfo, tree, data); |
961 | 1.62M | break; |
962 | | |
963 | 21 | case DISSECTOR_TYPE_CALLBACK: |
964 | 21 | len = (handle->dissector_func.dissector_type_callback)(tvb, pinfo, tree, data, handle->dissector_data); |
965 | 21 | break; |
966 | | |
967 | 0 | default: |
968 | 0 | ws_assert_not_reached(); |
969 | 1.62M | } |
970 | 1.16M | pinfo->current_proto = saved_proto; |
971 | 1.16M | pinfo->curr_proto_layer_num = saved_proto_layer_num; |
972 | | |
973 | 1.16M | return len; |
974 | 1.62M | } |
975 | | |
976 | | /* |
977 | | * Call a dissector through a handle. |
978 | | * If the protocol for that handle isn't enabled, return 0 without |
979 | | * calling the dissector. |
980 | | * Otherwise, if the handle refers to a new-style dissector, call the |
981 | | * dissector and return its return value, otherwise call it and return |
982 | | * the length of the tvbuff pointed to by the argument. |
983 | | */ |
984 | | |
985 | | static int |
986 | | call_dissector_work_error(dissector_handle_t handle, tvbuff_t *tvb, |
987 | | packet_info *pinfo_arg, proto_tree *tree, void *); |
988 | | |
989 | | static int |
990 | | call_dissector_work(dissector_handle_t handle, tvbuff_t *tvb, packet_info *pinfo, |
991 | | proto_tree *tree, bool add_proto_name, void *data) |
992 | 2.19M | { |
993 | 2.19M | const char *saved_proto; |
994 | 2.19M | int saved_proto_layer_num; |
995 | 2.19M | uint16_t saved_can_desegment; |
996 | 2.19M | int len; |
997 | 2.19M | unsigned saved_layers_len = 0; |
998 | 2.19M | unsigned saved_tree_count = tree ? tree->tree_data->count : 0; |
999 | 2.19M | unsigned saved_desegment_len = pinfo->desegment_len; |
1000 | 2.19M | bool consumed_none; |
1001 | | |
1002 | 2.19M | if (handle->protocol != NULL && |
1003 | 2.13M | !proto_is_protocol_enabled(handle->protocol)) { |
1004 | | /* |
1005 | | * The protocol isn't enabled. |
1006 | | */ |
1007 | 573k | return 0; |
1008 | 573k | } |
1009 | | |
1010 | 1.62M | saved_proto = pinfo->current_proto; |
1011 | 1.62M | saved_proto_layer_num = pinfo->curr_proto_layer_num; |
1012 | 1.62M | saved_can_desegment = pinfo->can_desegment; |
1013 | 1.62M | saved_layers_len = wmem_list_count(pinfo->layers); |
1014 | 1.62M | DISSECTOR_ASSERT(saved_layers_len < prefs.gui_max_tree_depth); |
1015 | | |
1016 | | /* |
1017 | | * can_desegment is set to 2 by anyone which offers the |
1018 | | * desegmentation api/service. |
1019 | | * Then every time a subdissector is called it is decremented |
1020 | | * by one. |
1021 | | * Thus only the subdissector immediately on top of whoever |
1022 | | * offers this service can use it. |
1023 | | * We save the current value of "can_desegment" for the |
1024 | | * benefit of TCP proxying dissectors such as SOCKS, so they |
1025 | | * can restore it and allow the dissectors they call to use |
1026 | | * the desegmentation service. |
1027 | | */ |
1028 | 1.62M | pinfo->saved_can_desegment = saved_can_desegment; |
1029 | 1.62M | pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0); |
1030 | 1.62M | if ((handle->protocol != NULL) && (!proto_is_bytes_pino(handle->protocol))) { |
1031 | 1.54M | pinfo->current_proto = |
1032 | 1.54M | proto_get_protocol_short_name(handle->protocol); |
1033 | | |
1034 | | /* |
1035 | | * Add the protocol name to the layers only if told to |
1036 | | * do so. Asn2wrs generated dissectors may be added |
1037 | | * multiple times otherwise. |
1038 | | */ |
1039 | | /* XXX Should we check for a duplicate layer here? */ |
1040 | 1.54M | if (add_proto_name) { |
1041 | 1.35M | add_layer(pinfo, proto_get_id(handle->protocol)); |
1042 | 1.35M | } |
1043 | 1.54M | } |
1044 | | |
1045 | 1.62M | if (pinfo->flags.in_error_pkt) { |
1046 | 156k | len = call_dissector_work_error(handle, tvb, pinfo, tree, data); |
1047 | 1.46M | } else { |
1048 | | /* |
1049 | | * Just call the subdissector. |
1050 | | */ |
1051 | 1.46M | len = call_dissector_through_handle(handle, tvb, pinfo, tree, data); |
1052 | 1.46M | } |
1053 | 1.62M | consumed_none = len == 0 || (pinfo->desegment_len != saved_desegment_len && pinfo->desegment_offset == 0); |
1054 | | /* If len == 0, then the dissector didn't accept the packet. |
1055 | | * In the latter case, the dissector accepted the packet, but didn't |
1056 | | * consume any bytes because they all belong in a later segment. |
1057 | | * In the latter case, we probably won't call a dissector here again |
1058 | | * on the next pass, so removing the layer keeps any *further* layers |
1059 | | * past this one the same on subsequent passes. |
1060 | | * |
1061 | | * XXX: DISSECTOR_ASSERT that the tree count didn't change? If the |
1062 | | * dissector didn't consume any bytes but added items to the tree, |
1063 | | * that's improper behavior and needs a rethink. We could also move the |
1064 | | * test that the packet didn't change desegment_offset and desegment_len |
1065 | | * while rejecting the packet from packet-tcp.c decode_tcp_ports to here. |
1066 | | */ |
1067 | 1.62M | if (handle->protocol != NULL && !proto_is_bytes_pino(handle->protocol) && add_proto_name && |
1068 | 996k | (consumed_none || (tree && saved_tree_count == tree->tree_data->count))) { |
1069 | | /* |
1070 | | * We've added a layer and either the dissector didn't |
1071 | | * consume any data or we didn't add any items to the |
1072 | | * tree. Remove it. |
1073 | | */ |
1074 | 74.5k | while (wmem_list_count(pinfo->layers) > saved_layers_len) { |
1075 | | /* |
1076 | | * Only reduce the layer number if the dissector didn't |
1077 | | * consume any data. Since tree can be NULL on |
1078 | | * the first pass, we cannot check it or it will |
1079 | | * break dissectors that rely on a stable value. |
1080 | | */ |
1081 | 38.0k | remove_last_layer(pinfo, consumed_none); |
1082 | 38.0k | } |
1083 | 36.5k | } |
1084 | 1.62M | pinfo->current_proto = saved_proto; |
1085 | 1.62M | pinfo->curr_proto_layer_num = saved_proto_layer_num; |
1086 | 1.62M | pinfo->can_desegment = saved_can_desegment; |
1087 | 1.62M | return len; |
1088 | 2.19M | } |
1089 | | |
1090 | | |
1091 | | static int |
1092 | | call_dissector_work_error(dissector_handle_t handle, tvbuff_t *tvb, |
1093 | | packet_info *pinfo_arg, proto_tree *tree, void *data) |
1094 | 156k | { |
1095 | 156k | packet_info *pinfo = pinfo_arg; |
1096 | 156k | const char *saved_proto; |
1097 | 156k | uint16_t saved_can_desegment; |
1098 | 156k | volatile int len = 0; |
1099 | 156k | bool save_writable; |
1100 | 156k | address save_dl_src; |
1101 | 156k | address save_dl_dst; |
1102 | 156k | address save_net_src; |
1103 | 156k | address save_net_dst; |
1104 | 156k | address save_src; |
1105 | 156k | address save_dst; |
1106 | 156k | uint32_t save_ptype; |
1107 | 156k | uint32_t save_srcport; |
1108 | 156k | uint32_t save_destport; |
1109 | | |
1110 | | /* |
1111 | | * This isn't a packet being transported inside |
1112 | | * the protocol whose dissector is calling us, |
1113 | | * it's a copy of a packet that caused an error |
1114 | | * in some protocol included in a packet that |
1115 | | * reports the error (e.g., an ICMP Unreachable |
1116 | | * packet). |
1117 | | */ |
1118 | | |
1119 | | /* |
1120 | | * Save the current state of the writability of |
1121 | | * the columns, and restore them after the |
1122 | | * dissector returns, so that the columns |
1123 | | * don't reflect the packet that got the error, |
1124 | | * they reflect the packet that reported the |
1125 | | * error. |
1126 | | */ |
1127 | 156k | saved_proto = pinfo->current_proto; |
1128 | 156k | saved_can_desegment = pinfo->can_desegment; |
1129 | | |
1130 | 156k | save_writable = col_get_writable(pinfo->cinfo, -1); |
1131 | 156k | col_set_writable(pinfo->cinfo, -1, false); |
1132 | 156k | copy_address_shallow(&save_dl_src, &pinfo->dl_src); |
1133 | 156k | copy_address_shallow(&save_dl_dst, &pinfo->dl_dst); |
1134 | 156k | copy_address_shallow(&save_net_src, &pinfo->net_src); |
1135 | 156k | copy_address_shallow(&save_net_dst, &pinfo->net_dst); |
1136 | 156k | copy_address_shallow(&save_src, &pinfo->src); |
1137 | 156k | copy_address_shallow(&save_dst, &pinfo->dst); |
1138 | 156k | save_ptype = pinfo->ptype; |
1139 | 156k | save_srcport = pinfo->srcport; |
1140 | 156k | save_destport = pinfo->destport; |
1141 | | |
1142 | | /* Dissect the contained packet. */ |
1143 | 156k | TRY { |
1144 | 156k | len = call_dissector_through_handle(handle, tvb,pinfo, tree, data); |
1145 | 156k | } |
1146 | 156k | CATCH(BoundsError) { |
1147 | | /* |
1148 | | * Restore the column writability and addresses and ports. |
1149 | | */ |
1150 | 25 | col_set_writable(pinfo->cinfo, -1, save_writable); |
1151 | 25 | copy_address_shallow(&pinfo->dl_src, &save_dl_src); |
1152 | 25 | copy_address_shallow(&pinfo->dl_dst, &save_dl_dst); |
1153 | 25 | copy_address_shallow(&pinfo->net_src, &save_net_src); |
1154 | 25 | copy_address_shallow(&pinfo->net_dst, &save_net_dst); |
1155 | 25 | copy_address_shallow(&pinfo->src, &save_src); |
1156 | 25 | copy_address_shallow(&pinfo->dst, &save_dst); |
1157 | 25 | pinfo->ptype = save_ptype; |
1158 | 25 | pinfo->srcport = save_srcport; |
1159 | 25 | pinfo->destport = save_destport; |
1160 | | |
1161 | | /* |
1162 | | * Restore the current protocol, so any |
1163 | | * "Short Frame" indication reflects that |
1164 | | * protocol, not the protocol for the |
1165 | | * packet that got the error. |
1166 | | */ |
1167 | 25 | pinfo->current_proto = saved_proto; |
1168 | | |
1169 | | /* |
1170 | | * Restore the desegmentability state. |
1171 | | */ |
1172 | 25 | pinfo->can_desegment = saved_can_desegment; |
1173 | | |
1174 | | /* |
1175 | | * Rethrow the exception, so this will be |
1176 | | * reported as a short frame. |
1177 | | */ |
1178 | 25 | RETHROW; |
1179 | 0 | } |
1180 | 156k | CATCH3(FragmentBoundsError, ContainedBoundsError, ReportedBoundsError) { |
1181 | | /* |
1182 | | * "ret" wasn't set because an exception was thrown |
1183 | | * before "call_dissector_through_handle()" returned. |
1184 | | * As it called something, at least one dissector |
1185 | | * accepted the packet, and, as an exception was |
1186 | | * thrown, not only was all the tvbuff dissected, |
1187 | | * a dissector tried dissecting past the end of |
1188 | | * the data in some tvbuff, so we'll assume that |
1189 | | * the entire tvbuff was dissected. |
1190 | | */ |
1191 | 48.2k | len = tvb_captured_length(tvb); |
1192 | 48.2k | } |
1193 | 156k | ENDTRY; |
1194 | | |
1195 | 156k | col_set_writable(pinfo->cinfo, -1, save_writable); |
1196 | 156k | copy_address_shallow(&pinfo->dl_src, &save_dl_src); |
1197 | 156k | copy_address_shallow(&pinfo->dl_dst, &save_dl_dst); |
1198 | 156k | copy_address_shallow(&pinfo->net_src, &save_net_src); |
1199 | 156k | copy_address_shallow(&pinfo->net_dst, &save_net_dst); |
1200 | 156k | copy_address_shallow(&pinfo->src, &save_src); |
1201 | 156k | copy_address_shallow(&pinfo->dst, &save_dst); |
1202 | 156k | pinfo->ptype = save_ptype; |
1203 | 156k | pinfo->srcport = save_srcport; |
1204 | 156k | pinfo->destport = save_destport; |
1205 | 156k | pinfo->want_pdu_tracking = 0; |
1206 | 156k | return len; |
1207 | 156k | } |
1208 | | |
1209 | | /* |
1210 | | * An entry in the hash table portion of a dissector table. |
1211 | | */ |
1212 | | struct dtbl_entry { |
1213 | | dissector_handle_t initial; |
1214 | | dissector_handle_t current; |
1215 | | }; |
1216 | | |
1217 | | /* Finds a dissector table by table name. */ |
1218 | | dissector_table_t |
1219 | | find_dissector_table(const char *name) |
1220 | 331k | { |
1221 | 331k | dissector_table_t dissector_table = (dissector_table_t) g_hash_table_lookup(dissector_tables, name); |
1222 | 331k | if (! dissector_table) { |
1223 | 0 | const char *new_name = (const char *) g_hash_table_lookup(dissector_table_aliases, name); |
1224 | 0 | if (new_name) { |
1225 | 0 | dissector_table = (dissector_table_t) g_hash_table_lookup(dissector_tables, new_name); |
1226 | 0 | } |
1227 | 0 | if (dissector_table) { |
1228 | 0 | ws_warning("%s is now %s", name, new_name); |
1229 | 0 | } |
1230 | 0 | } |
1231 | 331k | return dissector_table; |
1232 | 331k | } |
1233 | | |
1234 | | /* Find an entry in a uint dissector table. */ |
1235 | | static dtbl_entry_t * |
1236 | | find_uint_dtbl_entry(dissector_table_t sub_dissectors, const uint32_t pattern) |
1237 | 1.35M | { |
1238 | 1.35M | switch (sub_dissectors->type) { |
1239 | | |
1240 | 441k | case FT_UINT8: |
1241 | 1.00M | case FT_UINT16: |
1242 | 1.00M | case FT_UINT24: |
1243 | 1.35M | case FT_UINT32: |
1244 | | /* |
1245 | | * You can do a uint lookup in these tables. |
1246 | | */ |
1247 | 1.35M | break; |
1248 | 377 | case FT_NONE: |
1249 | | /* For now treat as uint */ |
1250 | 377 | break; |
1251 | | |
1252 | 0 | default: |
1253 | | /* |
1254 | | * But you can't do a uint lookup in any other types |
1255 | | * of tables. |
1256 | | */ |
1257 | 0 | ws_assert_not_reached(); |
1258 | 1.35M | } |
1259 | | |
1260 | | /* |
1261 | | * Find the entry. |
1262 | | */ |
1263 | 1.35M | return (dtbl_entry_t *)g_hash_table_lookup(sub_dissectors->hash_table, |
1264 | 1.35M | GUINT_TO_POINTER(pattern)); |
1265 | 1.35M | } |
1266 | | |
1267 | | #if 0 |
1268 | | static void |
1269 | | dissector_add_uint_sanity_check(const char *name, uint32_t pattern, dissector_handle_t handle, dissector_table_t sub_dissectors) |
1270 | | { |
1271 | | dtbl_entry_t *dtbl_entry; |
1272 | | |
1273 | | if (pattern == 0) { |
1274 | | ws_warning("%s: %s registering using a pattern of 0", |
1275 | | name, proto_get_protocol_filter_name(proto_get_id(handle->protocol))); |
1276 | | } |
1277 | | |
1278 | | dtbl_entry = g_hash_table_lookup(sub_dissectors->hash_table, GUINT_TO_POINTER(pattern)); |
1279 | | if (dtbl_entry != NULL) { |
1280 | | ws_warning("%s: %s registering using pattern %d already registered by %s", |
1281 | | name, proto_get_protocol_filter_name(proto_get_id(handle->protocol)), |
1282 | | pattern, proto_get_protocol_filter_name(proto_get_id(dtbl_entry->initial->protocol))); |
1283 | | } |
1284 | | } |
1285 | | #endif |
1286 | | |
1287 | | /* Get and check subdissector table and handle |
1288 | | * @return true if subdissector and handle exist */ |
1289 | | static bool |
1290 | | dissector_get_table_checked(const char *name, dissector_handle_t handle, dissector_table_t *sub_dissectors) |
1291 | 298k | { |
1292 | 298k | *sub_dissectors = find_dissector_table(name); |
1293 | | |
1294 | | /* |
1295 | | * Make sure the handle and the dissector table exist. |
1296 | | */ |
1297 | 298k | if (handle == NULL) { |
1298 | 0 | ws_dissector_oops("handle to register \"%s\" to doesn't exist\n", |
1299 | 0 | name); |
1300 | 0 | return false; |
1301 | 0 | } |
1302 | 298k | if (*sub_dissectors == NULL) { |
1303 | 0 | ws_dissector_oops("dissector table \"%s\" doesn't exist\n" |
1304 | 0 | "Protocol being registered is \"%s\"\n", |
1305 | 0 | name, proto_get_protocol_long_name(handle->protocol)); |
1306 | 0 | return false; |
1307 | 0 | } |
1308 | | |
1309 | 298k | return true; |
1310 | 298k | } |
1311 | | |
1312 | | static void |
1313 | | dissector_add_uint_real(const char *name _U_, const uint32_t pattern, dissector_handle_t handle, dissector_table_t sub_dissectors) |
1314 | 187k | { |
1315 | 187k | dtbl_entry_t *dtbl_entry; |
1316 | | |
1317 | 187k | switch (sub_dissectors->type) { |
1318 | | |
1319 | 19.5k | case FT_UINT8: |
1320 | 54.1k | case FT_UINT16: |
1321 | 54.9k | case FT_UINT24: |
1322 | 187k | case FT_UINT32: |
1323 | | /* |
1324 | | * You can do a uint lookup in these tables. |
1325 | | */ |
1326 | 187k | break; |
1327 | | |
1328 | 0 | default: |
1329 | | /* |
1330 | | * But you can't do a uint lookup in any other types |
1331 | | * of tables. |
1332 | | */ |
1333 | 0 | ws_assert_not_reached(); |
1334 | 187k | } |
1335 | | |
1336 | | #if 0 |
1337 | | dissector_add_uint_sanity_check(name, pattern, handle, sub_dissectors); |
1338 | | #endif |
1339 | | |
1340 | 187k | dtbl_entry = g_new(dtbl_entry_t, 1); |
1341 | 187k | dtbl_entry->current = handle; |
1342 | 187k | dtbl_entry->initial = dtbl_entry->current; |
1343 | | |
1344 | | /* do the table insertion */ |
1345 | 187k | g_hash_table_insert(sub_dissectors->hash_table, |
1346 | 187k | GUINT_TO_POINTER(pattern), (void *)dtbl_entry); |
1347 | 187k | } |
1348 | | |
1349 | | /* Add an entry to a uint dissector table. */ |
1350 | | void |
1351 | | dissector_add_uint(const char *name, const uint32_t pattern, dissector_handle_t handle) |
1352 | 177k | { |
1353 | 177k | dissector_table_t sub_dissectors; |
1354 | | |
1355 | 177k | if (!dissector_get_table_checked(name, handle, &sub_dissectors)) |
1356 | 0 | return; |
1357 | | |
1358 | 177k | dissector_add_uint_real(name, pattern, handle, sub_dissectors); |
1359 | | |
1360 | | /* |
1361 | | * Now, if this table supports "Decode As", add this handle |
1362 | | * to the list of handles that could be used for "Decode As" |
1363 | | * with this table, because it *is* being used with this table. |
1364 | | */ |
1365 | 177k | if (dissector_table_supports_decode_as(sub_dissectors)) |
1366 | 17.8k | dissector_add_for_decode_as(name, handle); |
1367 | 177k | } |
1368 | | |
1369 | | void dissector_add_uint_range(const char *name, range_t *range, |
1370 | | dissector_handle_t handle) |
1371 | 2.70k | { |
1372 | 2.70k | if (!range) { |
1373 | 0 | return; |
1374 | 0 | } |
1375 | | |
1376 | 2.70k | dissector_table_t sub_dissectors; |
1377 | 2.70k | uint32_t i, j; |
1378 | | |
1379 | 2.70k | if (!dissector_get_table_checked(name, handle, &sub_dissectors)) |
1380 | 0 | return; |
1381 | | |
1382 | 6.12k | for (i = 0; i < range->nranges; i++) { |
1383 | 9.87k | for (j = range->ranges[i].low; j < range->ranges[i].high; j++) |
1384 | 6.44k | dissector_add_uint_real(name, j, handle, sub_dissectors); |
1385 | 3.42k | dissector_add_uint_real(name, range->ranges[i].high, handle, sub_dissectors); |
1386 | 3.42k | } |
1387 | | /* |
1388 | | * Even an empty range would want a chance for |
1389 | | * Decode As, if the dissector table supports |
1390 | | * it. |
1391 | | */ |
1392 | 2.70k | if (dissector_table_supports_decode_as(sub_dissectors)) |
1393 | 2.56k | dissector_add_for_decode_as(name, handle); |
1394 | 2.70k | } |
1395 | | |
1396 | | static range_t* |
1397 | | dissector_add_range_preference(const char *name, dissector_handle_t handle, const char* range_str) |
1398 | 11.6k | { |
1399 | 11.6k | range_t** range; |
1400 | 11.6k | module_t *module; |
1401 | 11.6k | char *description, *title; |
1402 | 11.6k | dissector_table_t pref_dissector_table = find_dissector_table(name); |
1403 | 11.6k | int proto_id = proto_get_id(handle->protocol); |
1404 | 11.6k | uint32_t max_value = 0; |
1405 | | |
1406 | 11.6k | if (!pref_dissector_table) { |
1407 | 0 | ws_warning("Unable to find dissector table for %s", name); |
1408 | 0 | return NULL; |
1409 | 0 | } |
1410 | | |
1411 | | /* If a dissector is added for Decode As only, it's dissector |
1412 | | table value would default to 0. |
1413 | | Set up a preference value with that information |
1414 | | */ |
1415 | 11.6k | range = wmem_new0(wmem_epan_scope(), range_t*); |
1416 | | |
1417 | | /* If the dissector's protocol already has a preference module, use it */ |
1418 | 11.6k | const char* module_name = proto_get_protocol_filter_name(proto_id); |
1419 | 11.6k | module = prefs_find_module(module_name); |
1420 | 11.6k | if (module == NULL) { |
1421 | | /* Otherwise create a new one */ |
1422 | 5.00k | module = prefs_register_protocol(proto_id, NULL); |
1423 | 5.00k | } |
1424 | | |
1425 | 11.6k | const char *pref_suffix = dissector_handle_get_pref_suffix(handle); |
1426 | 11.6k | const char *fullname = wmem_strdup_printf(wmem_epan_scope(), "%s%s", name, pref_suffix); |
1427 | | |
1428 | | /* Some preference callback functions use the proto_reg_handoff_ |
1429 | | routine to apply preferences, which could duplicate the |
1430 | | registration of a preference. Check for that here */ |
1431 | 11.6k | if (prefs_find_preference(module, fullname) == NULL) { |
1432 | 11.5k | const char *handle_desc = dissector_handle_get_description(handle); |
1433 | 11.5k | if (g_strcmp0(range_str, "") > 0) { |
1434 | 7.71k | description = wmem_strdup_printf(wmem_epan_scope(), "%s %s(s) (default: %s)", |
1435 | 7.71k | handle_desc, pref_dissector_table->ui_name, range_str); |
1436 | 7.71k | } else { |
1437 | 3.82k | description = wmem_strdup_printf(wmem_epan_scope(), "%s %s(s)", |
1438 | 3.82k | handle_desc, pref_dissector_table->ui_name); |
1439 | 3.82k | } |
1440 | 11.5k | title = wmem_strdup_printf(wmem_epan_scope(), "%s %s(s)", handle_desc, pref_dissector_table->ui_name); |
1441 | | |
1442 | | /* Max value is based on datatype of dissector table */ |
1443 | 11.5k | switch (pref_dissector_table->type) { |
1444 | | |
1445 | 416 | case FT_UINT8: |
1446 | 416 | max_value = 0xFF; |
1447 | 416 | break; |
1448 | 11.0k | case FT_UINT16: |
1449 | 11.0k | max_value = 0xFFFF; |
1450 | 11.0k | break; |
1451 | 0 | case FT_UINT24: |
1452 | 0 | max_value = 0xFFFFFF; |
1453 | 0 | break; |
1454 | 48 | case FT_UINT32: |
1455 | 48 | max_value = 0xFFFFFFFF; |
1456 | 48 | break; |
1457 | | |
1458 | 0 | default: |
1459 | 0 | ws_error("The dissector table %s (%s) is not an integer type - are you using a buggy plugin?", name, pref_dissector_table->ui_name); |
1460 | 0 | ws_assert_not_reached(); |
1461 | 11.5k | } |
1462 | | |
1463 | 11.5k | range_convert_str(wmem_epan_scope(), range, range_str, max_value); |
1464 | 11.5k | prefs_register_decode_as_range_preference(module, fullname, title, description, range, max_value, name, handle_desc); |
1465 | 11.5k | } else { |
1466 | | /* We have a duplicate. This might just be the handoff routine |
1467 | | * getting called twice, which isn't ideal but we can ignore |
1468 | | * for now. Log it at a level that isn't printed by default. |
1469 | | */ |
1470 | 80 | ws_info("Registering automatic preference %s in %s twice", fullname, module_name); |
1471 | | /* Check this is just registering the same handle to the same |
1472 | | * preference, and not registering a different handle of the |
1473 | | * same protocol and the same pref_suffix to the same table. |
1474 | | */ |
1475 | 80 | dissector_handle_t dup_handle; |
1476 | 27.0k | for (GSList *entry = pref_dissector_table->dissector_handles; entry != NULL; entry = g_slist_next(entry)) |
1477 | 27.0k | { |
1478 | 27.0k | dup_handle = (dissector_handle_t)entry->data; |
1479 | 27.0k | if (handle->protocol != dup_handle->protocol) { |
1480 | 26.9k | continue; |
1481 | 26.9k | } |
1482 | 48 | if ((g_strcmp0(pref_suffix, dissector_handle_get_pref_suffix(dup_handle)) == 0) && |
1483 | 48 | (handle != dup_handle)) |
1484 | 0 | { |
1485 | 0 | const char *dissector_name = dissector_handle_get_dissector_name(handle); |
1486 | 0 | if (dissector_name == NULL) |
1487 | 0 | dissector_name = "(anonymous)"; |
1488 | 0 | const char *dup_dissector_name; |
1489 | 0 | dup_dissector_name = dissector_handle_get_dissector_name(dup_handle); |
1490 | 0 | if (dup_dissector_name == NULL) { |
1491 | 0 | dup_dissector_name = "(anonymous)"; |
1492 | 0 | } |
1493 | 0 | ws_dissector_bug("Dissectors %s and %s in dissector table %s would have the same Decode As preference\n", |
1494 | 0 | dissector_name, |
1495 | 0 | dup_dissector_name, |
1496 | 0 | name); |
1497 | 0 | } |
1498 | 48 | } |
1499 | 80 | } |
1500 | | |
1501 | 11.6k | return *range; |
1502 | 11.6k | } |
1503 | | |
1504 | | void dissector_add_uint_with_preference(const char *name, const uint32_t pattern, |
1505 | | dissector_handle_t handle) |
1506 | 6.17k | { |
1507 | 6.17k | char* range_str; |
1508 | | |
1509 | 6.17k | range_str = wmem_strdup_printf(NULL, "%d", pattern); |
1510 | 6.17k | dissector_add_range_preference(name, handle, range_str); |
1511 | 6.17k | wmem_free(NULL, range_str); |
1512 | 6.17k | dissector_add_uint(name, pattern, handle); |
1513 | 6.17k | } |
1514 | | |
1515 | | void dissector_add_uint_range_with_preference(const char *name, const char* range_str, |
1516 | | dissector_handle_t handle) |
1517 | 2.46k | { |
1518 | 2.46k | range_t* range; |
1519 | | |
1520 | 2.46k | range = dissector_add_range_preference(name, handle, range_str); |
1521 | 2.46k | dissector_add_uint_range(name, range, handle); |
1522 | 2.46k | } |
1523 | | |
1524 | | /* Delete the entry for a dissector in a uint dissector table |
1525 | | with a particular pattern. */ |
1526 | | |
1527 | | /* NOTE: this doesn't use the dissector call variable. It is included to */ |
1528 | | /* be consistent with the dissector_add_uint and more importantly to be used */ |
1529 | | /* if the technique of adding a temporary dissector is implemented. */ |
1530 | | /* If temporary dissectors are deleted, then the original dissector must */ |
1531 | | /* be available. */ |
1532 | | void |
1533 | | dissector_delete_uint(const char *name, const uint32_t pattern, |
1534 | | dissector_handle_t handle _U_) |
1535 | 16 | { |
1536 | 16 | dissector_table_t sub_dissectors = find_dissector_table(name); |
1537 | 16 | dtbl_entry_t *dtbl_entry; |
1538 | | |
1539 | | /* sanity check */ |
1540 | 16 | ws_assert(sub_dissectors); |
1541 | | |
1542 | | /* |
1543 | | * Find the entry. |
1544 | | */ |
1545 | 16 | dtbl_entry = find_uint_dtbl_entry(sub_dissectors, pattern); |
1546 | | |
1547 | 16 | if (dtbl_entry != NULL) { |
1548 | | /* |
1549 | | * Found - remove it. |
1550 | | */ |
1551 | 0 | g_hash_table_remove(sub_dissectors->hash_table, |
1552 | 0 | GUINT_TO_POINTER(pattern)); |
1553 | 0 | } |
1554 | 16 | } |
1555 | | |
1556 | | void dissector_delete_uint_range(const char *name, range_t *range, |
1557 | | dissector_handle_t handle) |
1558 | 16 | { |
1559 | 16 | uint32_t i, j; |
1560 | | |
1561 | 16 | if (range) { |
1562 | 0 | for (i = 0; i < range->nranges; i++) { |
1563 | 0 | for (j = range->ranges[i].low; j < range->ranges[i].high; j++) |
1564 | 0 | dissector_delete_uint(name, j, handle); |
1565 | 0 | dissector_delete_uint(name, range->ranges[i].high, handle); |
1566 | 0 | } |
1567 | 0 | } |
1568 | 16 | } |
1569 | | |
1570 | | /* Remove an entry from a guid dissector table. */ |
1571 | | void dissector_delete_guid(const char *name, guid_key* guid_val, dissector_handle_t handle) |
1572 | 0 | { |
1573 | 0 | dissector_table_t sub_dissectors; |
1574 | 0 | dtbl_entry_t *dtbl_entry; |
1575 | |
|
1576 | 0 | sub_dissectors = find_dissector_table(name); |
1577 | | |
1578 | | /* sanity check */ |
1579 | 0 | ws_assert(sub_dissectors); |
1580 | | |
1581 | | /* Find the table entry */ |
1582 | 0 | dtbl_entry = (dtbl_entry_t *)g_hash_table_lookup(sub_dissectors->hash_table, guid_val); |
1583 | |
|
1584 | 0 | if (dtbl_entry == NULL) { |
1585 | 0 | fprintf(stderr, "OOPS: guid not found in dissector table \"%s\"\n", name); |
1586 | 0 | return; |
1587 | 0 | } |
1588 | | |
1589 | | /* Make sure the handles match */ |
1590 | 0 | if (dtbl_entry->current != handle) { |
1591 | 0 | fprintf(stderr, "OOPS: handle does not match for guid in dissector table \"%s\"\n", name); |
1592 | 0 | return; |
1593 | 0 | } |
1594 | | |
1595 | | /* Remove the table entry */ |
1596 | 0 | g_hash_table_remove(sub_dissectors->hash_table, guid_val); |
1597 | 0 | } |
1598 | | |
1599 | | |
1600 | | static gboolean |
1601 | | dissector_delete_all_check (void *key _U_, void *value, void *user_data) |
1602 | 80 | { |
1603 | 80 | dtbl_entry_t *dtbl_entry = (dtbl_entry_t *) value; |
1604 | 80 | dissector_handle_t handle = (dissector_handle_t) user_data; |
1605 | | |
1606 | 80 | if (!dtbl_entry->current->protocol) { |
1607 | | /* |
1608 | | * Not all dissectors are registered with a protocol, so we need this |
1609 | | * check when running from dissector_delete_from_all_tables. |
1610 | | */ |
1611 | 0 | return FALSE; |
1612 | 0 | } |
1613 | | |
1614 | 80 | return (proto_get_id (dtbl_entry->current->protocol) == proto_get_id (handle->protocol)); |
1615 | 80 | } |
1616 | | |
1617 | | /* Delete all entries from a dissector table. */ |
1618 | | void dissector_delete_all(const char *name, dissector_handle_t handle) |
1619 | 288 | { |
1620 | 288 | dissector_table_t sub_dissectors = find_dissector_table(name); |
1621 | 288 | ws_assert (sub_dissectors); |
1622 | | |
1623 | 288 | g_hash_table_foreach_remove (sub_dissectors->hash_table, dissector_delete_all_check, handle); |
1624 | 288 | } |
1625 | | |
1626 | | static void |
1627 | | dissector_delete_from_table(void *key _U_, void *value, void *user_data) |
1628 | 0 | { |
1629 | 0 | dissector_table_t sub_dissectors = (dissector_table_t) value; |
1630 | 0 | ws_assert (sub_dissectors); |
1631 | |
|
1632 | 0 | dissector_handle_t handle = (dissector_handle_t) user_data; |
1633 | |
|
1634 | 0 | g_hash_table_foreach_remove(sub_dissectors->hash_table, dissector_delete_all_check, user_data); |
1635 | 0 | sub_dissectors->dissector_handles = g_slist_remove(sub_dissectors->dissector_handles, user_data); |
1636 | 0 | if (sub_dissectors->da_descriptions) |
1637 | 0 | g_hash_table_remove(sub_dissectors->da_descriptions, handle->description); |
1638 | 0 | } |
1639 | | |
1640 | | /* Delete handle from all tables and dissector_handles lists */ |
1641 | | static void |
1642 | | dissector_delete_from_all_tables(dissector_handle_t handle) |
1643 | 0 | { |
1644 | 0 | g_hash_table_foreach(dissector_tables, dissector_delete_from_table, handle); |
1645 | 0 | } |
1646 | | |
1647 | | /* Change the entry for a dissector in a uint dissector table |
1648 | | with a particular pattern to use a new dissector handle. */ |
1649 | | void |
1650 | | dissector_change_uint(const char *name, const uint32_t pattern, dissector_handle_t handle) |
1651 | 0 | { |
1652 | 0 | dissector_table_t sub_dissectors = find_dissector_table(name); |
1653 | 0 | dtbl_entry_t *dtbl_entry; |
1654 | | |
1655 | | /* sanity check */ |
1656 | 0 | ws_assert(sub_dissectors); |
1657 | | |
1658 | | /* |
1659 | | * See if the entry already exists. If so, reuse it. |
1660 | | */ |
1661 | 0 | dtbl_entry = find_uint_dtbl_entry(sub_dissectors, pattern); |
1662 | 0 | if (dtbl_entry != NULL) { |
1663 | | /* |
1664 | | * If there's no initial value, and the user said not |
1665 | | * to decode it, just remove the entry to save memory. |
1666 | | */ |
1667 | 0 | if (handle == NULL && dtbl_entry->initial == NULL) { |
1668 | 0 | g_hash_table_remove(sub_dissectors->hash_table, |
1669 | 0 | GUINT_TO_POINTER(pattern)); |
1670 | 0 | return; |
1671 | 0 | } |
1672 | 0 | dtbl_entry->current = handle; |
1673 | 0 | return; |
1674 | 0 | } |
1675 | | |
1676 | | /* |
1677 | | * Don't create an entry if there is no dissector handle - I.E. the |
1678 | | * user said not to decode something that wasn't being decoded |
1679 | | * in the first place. |
1680 | | */ |
1681 | 0 | if (handle == NULL) |
1682 | 0 | return; |
1683 | | |
1684 | 0 | dtbl_entry = g_new(dtbl_entry_t, 1); |
1685 | 0 | dtbl_entry->initial = NULL; |
1686 | 0 | dtbl_entry->current = handle; |
1687 | | |
1688 | | /* do the table insertion */ |
1689 | 0 | g_hash_table_insert(sub_dissectors->hash_table, |
1690 | 0 | GUINT_TO_POINTER(pattern), (void *)dtbl_entry); |
1691 | 0 | } |
1692 | | |
1693 | | /* Reset an entry in a uint dissector table to its initial value. */ |
1694 | | void |
1695 | | dissector_reset_uint(const char *name, const uint32_t pattern) |
1696 | 0 | { |
1697 | 0 | dissector_table_t sub_dissectors = find_dissector_table(name); |
1698 | 0 | dtbl_entry_t *dtbl_entry; |
1699 | | |
1700 | | /* sanity check */ |
1701 | 0 | ws_assert(sub_dissectors); |
1702 | | |
1703 | | /* |
1704 | | * Find the entry. |
1705 | | */ |
1706 | 0 | dtbl_entry = find_uint_dtbl_entry(sub_dissectors, pattern); |
1707 | |
|
1708 | 0 | if (dtbl_entry == NULL) |
1709 | 0 | return; |
1710 | | |
1711 | | /* |
1712 | | * Found - is there an initial value? |
1713 | | */ |
1714 | 0 | if (dtbl_entry->initial != NULL) { |
1715 | 0 | dtbl_entry->current = dtbl_entry->initial; |
1716 | 0 | } else { |
1717 | 0 | g_hash_table_remove(sub_dissectors->hash_table, |
1718 | 0 | GUINT_TO_POINTER(pattern)); |
1719 | 0 | } |
1720 | 0 | } |
1721 | | |
1722 | | /* Return true if an entry in a uint dissector table is found and has been |
1723 | | * changed (i.e. dissector_change_uint() has been called, such as from |
1724 | | * Decode As, prefs registered via dissector_add_uint_[range_]with_preference), |
1725 | | * etc.), otherwise return false. |
1726 | | */ |
1727 | | bool |
1728 | | dissector_is_uint_changed(dissector_table_t const sub_dissectors, const uint32_t uint_val) |
1729 | 260k | { |
1730 | 260k | if (sub_dissectors != NULL) { |
1731 | 260k | dtbl_entry_t *dtbl_entry = find_uint_dtbl_entry(sub_dissectors, uint_val); |
1732 | 260k | if (dtbl_entry != NULL) |
1733 | 134k | return (dtbl_entry->current != dtbl_entry->initial); |
1734 | 260k | } |
1735 | 125k | return false; |
1736 | 260k | } |
1737 | | |
1738 | | /* Look for a given value in a given uint dissector table and, if found, |
1739 | | call the dissector with the arguments supplied, and return the number |
1740 | | of bytes consumed by the dissector, otherwise return 0. */ |
1741 | | |
1742 | | int |
1743 | | dissector_try_uint_with_data(dissector_table_t sub_dissectors, const uint32_t uint_val, |
1744 | | tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
1745 | | const bool add_proto_name, void *data) |
1746 | 727k | { |
1747 | 727k | dtbl_entry_t *dtbl_entry; |
1748 | 727k | struct dissector_handle *handle; |
1749 | 727k | uint32_t saved_match_uint; |
1750 | 727k | int len; |
1751 | | |
1752 | 727k | dtbl_entry = find_uint_dtbl_entry(sub_dissectors, uint_val); |
1753 | 727k | if (dtbl_entry == NULL) { |
1754 | | /* |
1755 | | * There's no entry in the table for our value. |
1756 | | */ |
1757 | 153k | return 0; |
1758 | 153k | } |
1759 | | |
1760 | | /* |
1761 | | * Is there currently a dissector handle for this entry? |
1762 | | */ |
1763 | 573k | handle = dtbl_entry->current; |
1764 | 573k | if (handle == NULL) { |
1765 | | /* |
1766 | | * No - pretend this dissector didn't exist, |
1767 | | * so that other dissectors might have a chance |
1768 | | * to dissect this packet. |
1769 | | */ |
1770 | 0 | return 0; |
1771 | 0 | } |
1772 | | |
1773 | | /* |
1774 | | * Save the current value of "pinfo->match_uint", |
1775 | | * set it to the uint_val that matched, call the |
1776 | | * dissector, and restore "pinfo->match_uint". |
1777 | | */ |
1778 | 573k | saved_match_uint = pinfo->match_uint; |
1779 | 573k | pinfo->match_uint = uint_val; |
1780 | 573k | len = call_dissector_work(handle, tvb, pinfo, tree, add_proto_name, data); |
1781 | 573k | pinfo->match_uint = saved_match_uint; |
1782 | | |
1783 | | /* |
1784 | | * If a new-style dissector returned 0, it means that |
1785 | | * it didn't think this tvbuff represented a packet for |
1786 | | * its protocol, and didn't dissect anything. |
1787 | | * |
1788 | | * Old-style dissectors can't reject the packet. |
1789 | | * |
1790 | | * 0 is also returned if the protocol wasn't enabled. |
1791 | | * |
1792 | | * If the packet was rejected, we return 0, so that |
1793 | | * other dissectors might have a chance to dissect this |
1794 | | * packet, otherwise we return the dissected length. |
1795 | | */ |
1796 | 573k | return len; |
1797 | 573k | } |
1798 | | |
1799 | | int |
1800 | | dissector_try_uint(dissector_table_t sub_dissectors, const uint32_t uint_val, |
1801 | | tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
1802 | 245k | { |
1803 | | |
1804 | 245k | return dissector_try_uint_with_data(sub_dissectors, uint_val, tvb, pinfo, tree, true, NULL); |
1805 | 245k | } |
1806 | | |
1807 | | /* Look for a given value in a given uint dissector table and, if found, |
1808 | | return the dissector handle for that value. */ |
1809 | | dissector_handle_t |
1810 | | dissector_get_uint_handle(dissector_table_t const sub_dissectors, const uint32_t uint_val) |
1811 | 366k | { |
1812 | 366k | dtbl_entry_t *dtbl_entry; |
1813 | | |
1814 | 366k | dtbl_entry = find_uint_dtbl_entry(sub_dissectors, uint_val); |
1815 | 366k | if (dtbl_entry != NULL) |
1816 | 34.3k | return dtbl_entry->current; |
1817 | 332k | else |
1818 | 332k | return NULL; |
1819 | 366k | } |
1820 | | |
1821 | | dissector_handle_t |
1822 | | dissector_get_default_uint_handle(const char *name, const uint32_t uint_val) |
1823 | 56 | { |
1824 | 56 | dissector_table_t sub_dissectors = find_dissector_table(name); |
1825 | | |
1826 | 56 | if (sub_dissectors != NULL) { |
1827 | 56 | dtbl_entry_t *dtbl_entry = find_uint_dtbl_entry(sub_dissectors, uint_val); |
1828 | 56 | if (dtbl_entry != NULL) |
1829 | 56 | return dtbl_entry->initial; |
1830 | 56 | } |
1831 | 0 | return NULL; |
1832 | 56 | } |
1833 | | |
1834 | | /* Find an entry in a string dissector table. */ |
1835 | | static dtbl_entry_t * |
1836 | | find_string_dtbl_entry(dissector_table_t const sub_dissectors, const char *pattern) |
1837 | 25.7k | { |
1838 | 25.7k | dtbl_entry_t *ret; |
1839 | 25.7k | char *key; |
1840 | | |
1841 | 25.7k | switch (sub_dissectors->type) { |
1842 | | |
1843 | 25.7k | case FT_STRING: |
1844 | 25.7k | case FT_STRINGZ: |
1845 | 25.7k | case FT_STRINGZPAD: |
1846 | 25.7k | case FT_STRINGZTRUNC: |
1847 | | /* |
1848 | | * You can do a string lookup in these tables. |
1849 | | */ |
1850 | 25.7k | break; |
1851 | | |
1852 | 0 | default: |
1853 | | /* |
1854 | | * But you can't do a string lookup in any other types |
1855 | | * of tables. |
1856 | | */ |
1857 | 0 | ws_assert_not_reached(); |
1858 | 25.7k | } |
1859 | | |
1860 | 25.7k | if (sub_dissectors->param == STRING_CASE_INSENSITIVE) { |
1861 | 3.67k | key = g_ascii_strdown(pattern, -1); |
1862 | 22.1k | } else { |
1863 | 22.1k | key = g_strdup(pattern); |
1864 | 22.1k | } |
1865 | | |
1866 | | /* |
1867 | | * Find the entry. |
1868 | | */ |
1869 | 25.7k | ret = (dtbl_entry_t *)g_hash_table_lookup(sub_dissectors->hash_table, key); |
1870 | | |
1871 | 25.7k | g_free(key); |
1872 | | |
1873 | 25.7k | return ret; |
1874 | 25.7k | } |
1875 | | |
1876 | | /* Add an entry to a string dissector table. */ |
1877 | | void |
1878 | | dissector_add_string(const char *name, const char *pattern, |
1879 | | dissector_handle_t handle) |
1880 | 43.1k | { |
1881 | 43.1k | dissector_table_t sub_dissectors; |
1882 | 43.1k | dtbl_entry_t *dtbl_entry; |
1883 | 43.1k | char *key; |
1884 | | |
1885 | 43.1k | if (!dissector_get_table_checked(name, handle, &sub_dissectors)) |
1886 | 0 | return; |
1887 | | |
1888 | 43.1k | switch (sub_dissectors->type) { |
1889 | | |
1890 | 43.0k | case FT_STRING: |
1891 | 43.1k | case FT_STRINGZ: |
1892 | 43.1k | case FT_STRINGZPAD: |
1893 | 43.1k | case FT_STRINGZTRUNC: |
1894 | | /* |
1895 | | * You can do a string lookup in these tables. |
1896 | | */ |
1897 | 43.1k | break; |
1898 | | |
1899 | 0 | default: |
1900 | | /* |
1901 | | * But you can't do a string lookup in any other types |
1902 | | * of tables. |
1903 | | */ |
1904 | 0 | ws_assert_not_reached(); |
1905 | 43.1k | } |
1906 | | |
1907 | 43.1k | dtbl_entry = g_new(dtbl_entry_t, 1); |
1908 | 43.1k | dtbl_entry->current = handle; |
1909 | 43.1k | dtbl_entry->initial = dtbl_entry->current; |
1910 | | |
1911 | 43.1k | if (sub_dissectors->param == STRING_CASE_INSENSITIVE) { |
1912 | 7.31k | key = g_ascii_strdown(pattern, -1); |
1913 | 35.8k | } else { |
1914 | 35.8k | key = g_strdup(pattern); |
1915 | 35.8k | } |
1916 | | |
1917 | | /* do the table insertion */ |
1918 | 43.1k | g_hash_table_insert(sub_dissectors->hash_table, (void *)key, |
1919 | 43.1k | (void *)dtbl_entry); |
1920 | | |
1921 | | /* |
1922 | | * Now, if this table supports "Decode As", add this handle |
1923 | | * to the list of handles that could be used for "Decode As" |
1924 | | * with this table, because it *is* being used with this table. |
1925 | | */ |
1926 | 43.1k | if (dissector_table_supports_decode_as(sub_dissectors)) |
1927 | 8.30k | dissector_add_for_decode_as(name, handle); |
1928 | 43.1k | } |
1929 | | |
1930 | | /* Delete the entry for a dissector in a string dissector table |
1931 | | with a particular pattern. */ |
1932 | | |
1933 | | /* NOTE: this doesn't use the dissector call variable. It is included to */ |
1934 | | /* be consistent with the dissector_add_string and more importantly to */ |
1935 | | /* be used if the technique of adding a temporary dissector is */ |
1936 | | /* implemented. */ |
1937 | | /* If temporary dissectors are deleted, then the original dissector must */ |
1938 | | /* be available. */ |
1939 | | void |
1940 | | dissector_delete_string(const char *name, const char *pattern, |
1941 | | dissector_handle_t handle _U_) |
1942 | 0 | { |
1943 | 0 | dissector_table_t sub_dissectors = find_dissector_table(name); |
1944 | 0 | dtbl_entry_t *dtbl_entry; |
1945 | | |
1946 | | /* sanity check */ |
1947 | 0 | ws_assert(sub_dissectors); |
1948 | | |
1949 | | /* |
1950 | | * Find the entry. |
1951 | | */ |
1952 | 0 | dtbl_entry = find_string_dtbl_entry(sub_dissectors, pattern); |
1953 | |
|
1954 | 0 | if (dtbl_entry != NULL) { |
1955 | | /* |
1956 | | * Found - remove it. |
1957 | | */ |
1958 | 0 | g_hash_table_remove(sub_dissectors->hash_table, pattern); |
1959 | 0 | } |
1960 | 0 | } |
1961 | | |
1962 | | /* Change the entry for a dissector in a string dissector table |
1963 | | with a particular pattern to use a new dissector handle. */ |
1964 | | void |
1965 | | dissector_change_string(const char *name, const char *pattern, |
1966 | | dissector_handle_t handle) |
1967 | 0 | { |
1968 | 0 | dissector_table_t sub_dissectors = find_dissector_table(name); |
1969 | 0 | dtbl_entry_t *dtbl_entry; |
1970 | | |
1971 | | /* sanity check */ |
1972 | 0 | ws_assert(sub_dissectors); |
1973 | | |
1974 | | /* |
1975 | | * See if the entry already exists. If so, reuse it. |
1976 | | */ |
1977 | 0 | dtbl_entry = find_string_dtbl_entry(sub_dissectors, pattern); |
1978 | 0 | if (dtbl_entry != NULL) { |
1979 | | /* |
1980 | | * If there's no initial value, and the user said not |
1981 | | * to decode it, just remove the entry to save memory. |
1982 | | */ |
1983 | 0 | if (handle == NULL && dtbl_entry->initial == NULL) { |
1984 | 0 | g_hash_table_remove(sub_dissectors->hash_table, |
1985 | 0 | pattern); |
1986 | 0 | return; |
1987 | 0 | } |
1988 | 0 | dtbl_entry->current = handle; |
1989 | 0 | return; |
1990 | 0 | } |
1991 | | |
1992 | | /* |
1993 | | * Don't create an entry if there is no dissector handle - I.E. the |
1994 | | * user said not to decode something that wasn't being decoded |
1995 | | * in the first place. |
1996 | | */ |
1997 | 0 | if (handle == NULL) |
1998 | 0 | return; |
1999 | | |
2000 | 0 | dtbl_entry = g_new(dtbl_entry_t, 1); |
2001 | 0 | dtbl_entry->initial = NULL; |
2002 | 0 | dtbl_entry->current = handle; |
2003 | | |
2004 | | /* do the table insertion */ |
2005 | 0 | g_hash_table_insert(sub_dissectors->hash_table, (void *)g_strdup(pattern), |
2006 | 0 | (void *)dtbl_entry); |
2007 | 0 | } |
2008 | | |
2009 | | /* Reset an entry in a string sub-dissector table to its initial value. */ |
2010 | | void |
2011 | | dissector_reset_string(const char *name, const char *pattern) |
2012 | 0 | { |
2013 | 0 | dissector_table_t sub_dissectors = find_dissector_table(name); |
2014 | 0 | dtbl_entry_t *dtbl_entry; |
2015 | | |
2016 | | /* sanity check */ |
2017 | 0 | ws_assert(sub_dissectors); |
2018 | | |
2019 | | /* |
2020 | | * Find the entry. |
2021 | | */ |
2022 | 0 | dtbl_entry = find_string_dtbl_entry(sub_dissectors, pattern); |
2023 | |
|
2024 | 0 | if (dtbl_entry == NULL) |
2025 | 0 | return; |
2026 | | |
2027 | | /* |
2028 | | * Found - is there an initial value? |
2029 | | */ |
2030 | 0 | if (dtbl_entry->initial != NULL) { |
2031 | 0 | dtbl_entry->current = dtbl_entry->initial; |
2032 | 0 | } else { |
2033 | 0 | g_hash_table_remove(sub_dissectors->hash_table, pattern); |
2034 | 0 | } |
2035 | 0 | } |
2036 | | |
2037 | | /* Return true if an entry in a uint dissector table is found and has been |
2038 | | * changed (i.e. dissector_change_uint() has been called, such as from |
2039 | | * Decode As, prefs registered via dissector_add_uint_[range_]with_preference), |
2040 | | * etc.), otherwise return false. |
2041 | | */ |
2042 | | bool |
2043 | | dissector_is_string_changed(dissector_table_t const sub_dissectors, const char *string) |
2044 | 0 | { |
2045 | 0 | if (sub_dissectors != NULL) { |
2046 | 0 | dtbl_entry_t *dtbl_entry = find_string_dtbl_entry(sub_dissectors, string); |
2047 | 0 | if (dtbl_entry != NULL) |
2048 | 0 | return (dtbl_entry->current != dtbl_entry->initial); |
2049 | 0 | } |
2050 | 0 | return false; |
2051 | 0 | } |
2052 | | |
2053 | | /* Look for a given string in a given dissector table and, if found, call |
2054 | | the dissector with the arguments supplied, and return length of dissected data, |
2055 | | otherwise return 0. */ |
2056 | | int |
2057 | | dissector_try_string_with_data(dissector_table_t sub_dissectors, const char *string, |
2058 | | tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const bool add_proto_name, void *data) |
2059 | 24.8k | { |
2060 | 24.8k | dtbl_entry_t *dtbl_entry; |
2061 | 24.8k | struct dissector_handle *handle; |
2062 | 24.8k | int len; |
2063 | 24.8k | const char *saved_match_string; |
2064 | | |
2065 | | /* XXX ASSERT instead ? */ |
2066 | 24.8k | if (!string) return 0; |
2067 | 24.8k | dtbl_entry = find_string_dtbl_entry(sub_dissectors, string); |
2068 | 24.8k | if (dtbl_entry != NULL) { |
2069 | | /* |
2070 | | * Is there currently a dissector handle for this entry? |
2071 | | */ |
2072 | 19.1k | handle = dtbl_entry->current; |
2073 | 19.1k | if (handle == NULL) { |
2074 | | /* |
2075 | | * No - pretend this dissector didn't exist, |
2076 | | * so that other dissectors might have a chance |
2077 | | * to dissect this packet. |
2078 | | */ |
2079 | 0 | return 0; |
2080 | 0 | } |
2081 | | |
2082 | | /* |
2083 | | * Save the current value of "pinfo->match_string", |
2084 | | * set it to the string that matched, call the |
2085 | | * dissector, and restore "pinfo->match_string". |
2086 | | */ |
2087 | 19.1k | saved_match_string = pinfo->match_string; |
2088 | 19.1k | pinfo->match_string = string; |
2089 | 19.1k | len = call_dissector_work(handle, tvb, pinfo, tree, add_proto_name, data); |
2090 | 19.1k | pinfo->match_string = saved_match_string; |
2091 | | |
2092 | | /* |
2093 | | * If a new-style dissector returned 0, it means that |
2094 | | * it didn't think this tvbuff represented a packet for |
2095 | | * its protocol, and didn't dissect anything. |
2096 | | * |
2097 | | * Old-style dissectors can't reject the packet. |
2098 | | * |
2099 | | * 0 is also returned if the protocol wasn't enabled. |
2100 | | * |
2101 | | * If the packet was rejected, we return 0, so that |
2102 | | * other dissectors might have a chance to dissect this |
2103 | | * packet, otherwise we return the dissected length. |
2104 | | */ |
2105 | 19.1k | return len; |
2106 | 19.1k | } |
2107 | 5.72k | return 0; |
2108 | 24.8k | } |
2109 | | |
2110 | | /* Look for a given value in a given string dissector table and, if found, |
2111 | | return the dissector handle for that value. */ |
2112 | | dissector_handle_t |
2113 | | dissector_get_string_handle(dissector_table_t sub_dissectors, |
2114 | | const char *string) |
2115 | 897 | { |
2116 | 897 | dtbl_entry_t *dtbl_entry; |
2117 | | |
2118 | | /* XXX ASSERT instead ? */ |
2119 | 897 | if (!string) return NULL; |
2120 | 897 | dtbl_entry = find_string_dtbl_entry(sub_dissectors, string); |
2121 | 897 | if (dtbl_entry != NULL) |
2122 | 6 | return dtbl_entry->current; |
2123 | 891 | else |
2124 | 891 | return NULL; |
2125 | 897 | } |
2126 | | |
2127 | | dissector_handle_t |
2128 | | dissector_get_default_string_handle(const char *name, const char *string) |
2129 | 0 | { |
2130 | 0 | dissector_table_t sub_dissectors; |
2131 | | |
2132 | | /* XXX ASSERT instead ? */ |
2133 | 0 | if (!string) return NULL; |
2134 | 0 | sub_dissectors = find_dissector_table(name); |
2135 | 0 | if (sub_dissectors != NULL) { |
2136 | 0 | dtbl_entry_t *dtbl_entry = find_string_dtbl_entry(sub_dissectors, string); |
2137 | 0 | if (dtbl_entry != NULL) |
2138 | 0 | return dtbl_entry->initial; |
2139 | 0 | } |
2140 | 0 | return NULL; |
2141 | 0 | } |
2142 | | |
2143 | | /* Add an entry to a "custom" dissector table. */ |
2144 | | void dissector_add_custom_table_handle(const char *name, void *pattern, dissector_handle_t handle) |
2145 | 24.3k | { |
2146 | 24.3k | dissector_table_t sub_dissectors; |
2147 | 24.3k | dtbl_entry_t *dtbl_entry; |
2148 | | |
2149 | 24.3k | if (!dissector_get_table_checked(name, handle, &sub_dissectors)) |
2150 | 0 | return; |
2151 | | |
2152 | 24.3k | ws_assert(sub_dissectors->type == FT_BYTES); |
2153 | | |
2154 | 24.3k | dtbl_entry = g_new(dtbl_entry_t, 1); |
2155 | 24.3k | dtbl_entry->current = handle; |
2156 | 24.3k | dtbl_entry->initial = dtbl_entry->current; |
2157 | | |
2158 | | /* do the table insertion */ |
2159 | 24.3k | g_hash_table_insert(sub_dissectors->hash_table, (void *)pattern, |
2160 | 24.3k | (void *)dtbl_entry); |
2161 | | |
2162 | | /* |
2163 | | * Now, if this table supports "Decode As", add this handle |
2164 | | * to the list of handles that could be used for "Decode As" |
2165 | | * with this table, because it *is* being used with this table. |
2166 | | */ |
2167 | 24.3k | if (dissector_table_supports_decode_as(sub_dissectors)) |
2168 | 0 | dissector_add_for_decode_as(name, handle); |
2169 | 24.3k | } |
2170 | | |
2171 | | dissector_handle_t dissector_get_custom_table_handle(dissector_table_t sub_dissectors, void *key) |
2172 | 32.0k | { |
2173 | 32.0k | dtbl_entry_t *dtbl_entry = (dtbl_entry_t *)g_hash_table_lookup(sub_dissectors->hash_table, key); |
2174 | | |
2175 | 32.0k | if (dtbl_entry != NULL) |
2176 | 8.86k | return dtbl_entry->current; |
2177 | | |
2178 | 23.1k | return NULL; |
2179 | 32.0k | } |
2180 | | /* Add an entry to a guid dissector table. */ |
2181 | | void dissector_add_guid(const char *name, guid_key* guid_val, dissector_handle_t handle) |
2182 | 1.61k | { |
2183 | 1.61k | dissector_table_t sub_dissectors; |
2184 | 1.61k | dtbl_entry_t *dtbl_entry; |
2185 | | |
2186 | 1.61k | if (!dissector_get_table_checked(name, handle, &sub_dissectors)) |
2187 | 0 | return; |
2188 | | |
2189 | 1.61k | if (sub_dissectors->type != FT_GUID) { |
2190 | 0 | ws_assert_not_reached(); |
2191 | 0 | } |
2192 | | |
2193 | 1.61k | dtbl_entry = g_new(dtbl_entry_t, 1); |
2194 | 1.61k | dtbl_entry->current = handle; |
2195 | 1.61k | dtbl_entry->initial = dtbl_entry->current; |
2196 | | |
2197 | | /* do the table insertion */ |
2198 | 1.61k | g_hash_table_insert(sub_dissectors->hash_table, |
2199 | 1.61k | guid_val, (void *)dtbl_entry); |
2200 | | |
2201 | | /* |
2202 | | * Now, if this table supports "Decode As", add this handle |
2203 | | * to the list of handles that could be used for "Decode As" |
2204 | | * with this table, because it *is* being used with this table. |
2205 | | */ |
2206 | 1.61k | if (dissector_table_supports_decode_as(sub_dissectors)) |
2207 | 1.52k | dissector_add_for_decode_as(name, handle); |
2208 | 1.61k | } |
2209 | | |
2210 | | /* Look for a given value in a given guid dissector table and, if found, |
2211 | | call the dissector with the arguments supplied, and return true, |
2212 | | otherwise return false. */ |
2213 | | int dissector_try_guid_with_data(dissector_table_t sub_dissectors, |
2214 | | guid_key* guid_val, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const bool add_proto_name, void *data) |
2215 | 0 | { |
2216 | 0 | dtbl_entry_t *dtbl_entry; |
2217 | 0 | struct dissector_handle *handle; |
2218 | 0 | int len; |
2219 | |
|
2220 | 0 | dtbl_entry = (dtbl_entry_t *)g_hash_table_lookup(sub_dissectors->hash_table, guid_val); |
2221 | 0 | if (dtbl_entry != NULL) { |
2222 | | /* |
2223 | | * Is there currently a dissector handle for this entry? |
2224 | | */ |
2225 | 0 | handle = dtbl_entry->current; |
2226 | 0 | if (handle == NULL) { |
2227 | | /* |
2228 | | * No - pretend this dissector didn't exist, |
2229 | | * so that other dissectors might have a chance |
2230 | | * to dissect this packet. |
2231 | | */ |
2232 | 0 | return 0; |
2233 | 0 | } |
2234 | | |
2235 | | /* |
2236 | | * Save the current value of "pinfo->match_uint", |
2237 | | * set it to the uint_val that matched, call the |
2238 | | * dissector, and restore "pinfo->match_uint". |
2239 | | */ |
2240 | 0 | len = call_dissector_work(handle, tvb, pinfo, tree, add_proto_name, data); |
2241 | | |
2242 | | /* |
2243 | | * If a new-style dissector returned 0, it means that |
2244 | | * it didn't think this tvbuff represented a packet for |
2245 | | * its protocol, and didn't dissect anything. |
2246 | | * |
2247 | | * Old-style dissectors can't reject the packet. |
2248 | | * |
2249 | | * 0 is also returned if the protocol wasn't enabled. |
2250 | | * |
2251 | | * If the packet was rejected, we return 0, so that |
2252 | | * other dissectors might have a chance to dissect this |
2253 | | * packet, otherwise we return the dissected length. |
2254 | | */ |
2255 | 0 | return len; |
2256 | 0 | } |
2257 | 0 | return 0; |
2258 | 0 | } |
2259 | | |
2260 | | /** Look for a given value in a given guid dissector table and, if found, |
2261 | | * return the current dissector handle for that value. |
2262 | | * |
2263 | | * @param[in] sub_dissectors Dissector table to search. |
2264 | | * @param[in] guid_val Value to match. |
2265 | | * @return The matching dissector handle on success, NULL if no match is found. |
2266 | | */ |
2267 | | dissector_handle_t dissector_get_guid_handle( |
2268 | | dissector_table_t const sub_dissectors, guid_key* guid_val) |
2269 | 0 | { |
2270 | 0 | dtbl_entry_t *dtbl_entry; |
2271 | |
|
2272 | 0 | dtbl_entry = (dtbl_entry_t *)g_hash_table_lookup(sub_dissectors->hash_table, guid_val); |
2273 | 0 | if (dtbl_entry != NULL) |
2274 | 0 | return dtbl_entry->current; |
2275 | 0 | else |
2276 | 0 | return NULL; |
2277 | 0 | } |
2278 | | |
2279 | | /* Use the currently assigned payload dissector for the dissector table and, |
2280 | | if any, call the dissector with the arguments supplied, and return the |
2281 | | number of bytes consumed, otherwise return 0. */ |
2282 | | int dissector_try_payload_with_data(dissector_table_t sub_dissectors, |
2283 | | tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const bool add_proto_name, void *data) |
2284 | 377 | { |
2285 | 377 | return dissector_try_uint_with_data(sub_dissectors, 0, tvb, pinfo, tree, add_proto_name, data); |
2286 | 377 | } |
2287 | | |
2288 | | /* Change the entry for a dissector in a payload (FT_NONE) dissector table |
2289 | | with a particular pattern to use a new dissector handle. */ |
2290 | | void dissector_change_payload(const char *name, dissector_handle_t handle) |
2291 | 0 | { |
2292 | 0 | dissector_change_uint(name, 0, handle); |
2293 | 0 | } |
2294 | | |
2295 | | /* Reset payload (FT_NONE) dissector table to its initial value. */ |
2296 | | void dissector_reset_payload(const char *name) |
2297 | 0 | { |
2298 | 0 | dissector_reset_uint(name, 0); |
2299 | 0 | } |
2300 | | |
2301 | | /* Given a payload dissector table (type FT_NONE), return the handle of |
2302 | | the dissector that is currently active, i.e. that was selected via |
2303 | | Decode As. */ |
2304 | | dissector_handle_t |
2305 | | dissector_get_payload_handle(dissector_table_t const dissector_table) |
2306 | 0 | { |
2307 | 0 | return dissector_get_uint_handle(dissector_table, 0); |
2308 | 0 | } |
2309 | | |
2310 | | dissector_handle_t |
2311 | | dtbl_entry_get_handle (dtbl_entry_t *dtbl_entry) |
2312 | 0 | { |
2313 | 0 | return dtbl_entry->current; |
2314 | 0 | } |
2315 | | |
2316 | | static int |
2317 | | dissector_compare_filter_name(const void *dissector_a, const void *dissector_b) |
2318 | 178k | { |
2319 | 178k | const struct dissector_handle *a = (const struct dissector_handle *)dissector_a; |
2320 | 178k | const struct dissector_handle *b = (const struct dissector_handle *)dissector_b; |
2321 | 178k | const char *a_name, *b_name; |
2322 | 178k | int ret; |
2323 | | |
2324 | 178k | if (a->protocol == NULL) |
2325 | 48 | a_name = ""; |
2326 | 178k | else |
2327 | 178k | a_name = proto_get_protocol_filter_name(proto_get_id(a->protocol)); |
2328 | | |
2329 | 178k | if (b->protocol == NULL) |
2330 | 96 | b_name = ""; |
2331 | 178k | else |
2332 | 178k | b_name = proto_get_protocol_filter_name(proto_get_id(b->protocol)); |
2333 | | |
2334 | 178k | ret = strcmp(a_name, b_name); |
2335 | 178k | return ret; |
2336 | 178k | } |
2337 | | |
2338 | | void |
2339 | | packet_all_tables_sort_handles(void) |
2340 | 16 | { |
2341 | 16 | GHashTableIter iter; |
2342 | 16 | g_hash_table_iter_init(&iter, dissector_tables); |
2343 | 16 | void *key, *value; |
2344 | 16 | dissector_table_t table; |
2345 | 9.71k | while (g_hash_table_iter_next(&iter, &key, &value)) { |
2346 | 9.69k | table = (dissector_table_t)value; |
2347 | 9.69k | table->dissector_handles = g_slist_sort(table->dissector_handles, (GCompareFunc)dissector_compare_filter_name); |
2348 | 9.69k | } |
2349 | | /* Any handles added to a table after this (e.g., by a Lua dissector, |
2350 | | * by reloading Lua dissectors, by a UAT or other preference) will |
2351 | | * be added using g_slist_insert_sorted. */ |
2352 | 16 | all_tables_handles_sorted = true; |
2353 | 16 | } |
2354 | | |
2355 | | /* Add a handle to the list of handles that *could* be used with this |
2356 | | table. That list is used by the "Decode As"/"-d" code in the UI. */ |
2357 | | void |
2358 | | dissector_add_for_decode_as(const char *name, dissector_handle_t handle) |
2359 | 48.8k | { |
2360 | 48.8k | dissector_table_t sub_dissectors; |
2361 | 48.8k | dissector_handle_t dup_handle; |
2362 | | |
2363 | 48.8k | if (!dissector_get_table_checked(name, handle, &sub_dissectors)) |
2364 | 0 | return; |
2365 | | |
2366 | 48.8k | const char *dissector_name; |
2367 | 48.8k | dissector_name = dissector_handle_get_dissector_name(handle); |
2368 | 48.8k | if (dissector_name == NULL) |
2369 | 5.07k | dissector_name = "(anonymous)"; |
2370 | | |
2371 | | /* |
2372 | | * Make sure it supports Decode As. |
2373 | | */ |
2374 | 48.8k | if (!dissector_table_supports_decode_as(sub_dissectors)) { |
2375 | 0 | ws_dissector_bug("Registering dissector %s for protocol %s in dissector table %s, which doesn't support Decode As\n", |
2376 | 0 | dissector_name, |
2377 | 0 | proto_get_protocol_short_name(handle->protocol), |
2378 | 0 | name); |
2379 | 0 | return; |
2380 | 0 | } |
2381 | | |
2382 | | /* For Decode As selection to work, there has to be a description. |
2383 | | * One is generated if there's a protocol (PINOs are used in some |
2384 | | * cases to guarantee unique descriptions), but some dissectors are |
2385 | | * registered without a protocol. That is allowed for fixed tables |
2386 | | * that don't support Decode As. |
2387 | | */ |
2388 | 48.8k | if (handle->description == NULL) { |
2389 | 0 | ws_dissector_bug("Cannot register dissector %s in dissector table %s for Decode As without a protocol or description\n", |
2390 | 0 | dissector_name, name); |
2391 | 0 | return; |
2392 | 0 | } |
2393 | | |
2394 | | /* Ensure that the description is unique in the table, so that Decode As |
2395 | | * selection and UAT preference writing works. |
2396 | | * |
2397 | | * XXX - We could do the insert first and then check the return value, |
2398 | | * saving on a hash comparison. (The failure mode would be slightly |
2399 | | * different, as it would become last insertion wins.) |
2400 | | */ |
2401 | 48.8k | dup_handle = g_hash_table_lookup(sub_dissectors->da_descriptions, handle->description); |
2402 | 48.8k | if (dup_handle != NULL) { |
2403 | | /* Is this a different handle with the same description, or |
2404 | | * just trying to insert the same handle a second time? */ |
2405 | 9.79k | if (dup_handle != handle) { |
2406 | 0 | const char *dup_dissector_name; |
2407 | |
|
2408 | 0 | dup_dissector_name = dissector_handle_get_dissector_name(dup_handle); |
2409 | 0 | if (dup_dissector_name == NULL) |
2410 | 0 | dup_dissector_name = "(anonymous)"; |
2411 | 0 | ws_dissector_bug("Dissectors %s and %s in dissector table %s have the same description %s\n", |
2412 | 0 | dissector_name, |
2413 | 0 | dup_dissector_name, |
2414 | 0 | name, handle->description); |
2415 | 0 | } |
2416 | 9.79k | return; |
2417 | 9.79k | } |
2418 | | |
2419 | | /* Add the dissector as a dependency |
2420 | | (some dissector tables don't have protocol association, so there is |
2421 | | the need for the NULL check */ |
2422 | 39.0k | if (sub_dissectors->protocol != NULL) |
2423 | 37.6k | register_depend_dissector(proto_get_protocol_short_name(sub_dissectors->protocol), proto_get_protocol_short_name(handle->protocol)); |
2424 | | |
2425 | | /* Add it to the list. */ |
2426 | 39.0k | g_hash_table_insert(sub_dissectors->da_descriptions, (void *)handle->description, handle); |
2427 | 39.0k | if (all_tables_handles_sorted) { |
2428 | 0 | sub_dissectors->dissector_handles = |
2429 | 0 | g_slist_insert_sorted(sub_dissectors->dissector_handles, (void *)handle, (GCompareFunc)dissector_compare_filter_name); |
2430 | 39.0k | } else { |
2431 | 39.0k | sub_dissectors->dissector_handles = |
2432 | 39.0k | g_slist_prepend(sub_dissectors->dissector_handles, (void *)handle); |
2433 | 39.0k | } |
2434 | 39.0k | } |
2435 | | |
2436 | | void dissector_add_for_decode_as_with_preference(const char *name, |
2437 | | dissector_handle_t handle) |
2438 | 2.97k | { |
2439 | | /* If a dissector is added for Decode As only, it's dissector |
2440 | | table value would default to 0. |
2441 | | Set up a preference value with that information |
2442 | | */ |
2443 | 2.97k | dissector_add_range_preference(name, handle, ""); |
2444 | | |
2445 | 2.97k | dissector_add_for_decode_as(name, handle); |
2446 | 2.97k | } |
2447 | | |
2448 | | dissector_handle_t |
2449 | | dtbl_entry_get_initial_handle (dtbl_entry_t *dtbl_entry) |
2450 | 0 | { |
2451 | 0 | return dtbl_entry->initial; |
2452 | 0 | } |
2453 | | |
2454 | | GSList * |
2455 | 12 | dissector_table_get_dissector_handles(dissector_table_t dissector_table) { |
2456 | 12 | if (!dissector_table) |
2457 | 0 | return NULL; |
2458 | | |
2459 | 12 | return dissector_table->dissector_handles; |
2460 | 12 | } |
2461 | | |
2462 | | /* |
2463 | | * Data structure used as user data when iterating dissector handles |
2464 | | */ |
2465 | | typedef struct lookup_entry { |
2466 | | const char* dissector_description; |
2467 | | dissector_handle_t handle; |
2468 | | } lookup_entry_t; |
2469 | | |
2470 | | /* |
2471 | | * A callback function to changed a dissector_handle if matched |
2472 | | * This is used when iterating a dissector table |
2473 | | */ |
2474 | | static void |
2475 | | find_dissector_in_table(void *item, void *user_data) |
2476 | 0 | { |
2477 | 0 | dissector_handle_t handle = (dissector_handle_t)item; |
2478 | 0 | lookup_entry_t * lookup = (lookup_entry_t *)user_data; |
2479 | 0 | const char *description = dissector_handle_get_description(handle); |
2480 | 0 | if (description && strcmp(lookup->dissector_description, description) == 0) { |
2481 | 0 | lookup->handle = handle; |
2482 | 0 | } |
2483 | 0 | } |
2484 | | |
2485 | | dissector_handle_t dissector_table_get_dissector_handle(dissector_table_t dissector_table, const char* description) |
2486 | 0 | { |
2487 | | /* Can this even be called for tables that don't support Decode As? */ |
2488 | 0 | if (dissector_table->da_descriptions) { |
2489 | 0 | return g_hash_table_lookup(dissector_table->da_descriptions, description); |
2490 | 0 | } |
2491 | | |
2492 | 0 | lookup_entry_t lookup; |
2493 | |
|
2494 | 0 | lookup.dissector_description = description; |
2495 | 0 | lookup.handle = NULL; |
2496 | |
|
2497 | 0 | g_slist_foreach(dissector_table->dissector_handles, find_dissector_in_table, &lookup); |
2498 | 0 | return lookup.handle; |
2499 | 0 | } |
2500 | | |
2501 | | ftenum_t |
2502 | 0 | dissector_table_get_type(dissector_table_t dissector_table) { |
2503 | 0 | if (!dissector_table) return FT_NONE; |
2504 | 0 | return dissector_table->type; |
2505 | 0 | } |
2506 | | |
2507 | | inline void |
2508 | | dissector_table_allow_decode_as_internal(dissector_table_t dissector_table) |
2509 | 1.21k | { |
2510 | 1.21k | if (dissector_table->da_descriptions == NULL) { |
2511 | 1.08k | dissector_table->da_descriptions = g_hash_table_new(wmem_str_hash, g_str_equal); |
2512 | 1.08k | } |
2513 | 1.21k | } |
2514 | | |
2515 | | void |
2516 | | dissector_table_allow_decode_as(dissector_table_t dissector_table) |
2517 | 0 | { |
2518 | 0 | dissector_table_allow_decode_as_internal(dissector_table); |
2519 | 0 | } |
2520 | | |
2521 | | inline bool |
2522 | | dissector_table_supports_decode_as(dissector_table_t dissector_table) |
2523 | 307k | { |
2524 | 307k | return dissector_table->da_descriptions != NULL; |
2525 | 307k | } |
2526 | | |
2527 | | static int |
2528 | | uuid_equal(const void *k1, const void *k2) |
2529 | 768 | { |
2530 | 768 | const guid_key *key1 = (const guid_key *)k1; |
2531 | 768 | const guid_key *key2 = (const guid_key *)k2; |
2532 | 768 | return ((memcmp(&key1->guid, &key2->guid, sizeof (e_guid_t)) == 0) |
2533 | 16 | && (key1->ver == key2->ver)); |
2534 | 768 | } |
2535 | | |
2536 | | static unsigned |
2537 | | uuid_hash(const void *k) |
2538 | 1.61k | { |
2539 | 1.61k | const guid_key *key = (const guid_key *)k; |
2540 | | /* This isn't perfect, but the Data1 part of these is almost always unique. */ |
2541 | 1.61k | return key->guid.data1; |
2542 | 1.61k | } |
2543 | | |
2544 | | /**************************************************/ |
2545 | | /* */ |
2546 | | /* Routines to walk dissector tables */ |
2547 | | /* */ |
2548 | | /**************************************************/ |
2549 | | |
2550 | | typedef struct dissector_foreach_info { |
2551 | | void * caller_data; |
2552 | | DATFunc caller_func; |
2553 | | GHFunc next_func; |
2554 | | const char *table_name; |
2555 | | ftenum_t selector_type; |
2556 | | } dissector_foreach_info_t; |
2557 | | |
2558 | | /* |
2559 | | * Called for each entry in a dissector table. |
2560 | | */ |
2561 | | static void |
2562 | | dissector_table_foreach_func (void *key, void *value, void *user_data) |
2563 | 960 | { |
2564 | 960 | dissector_foreach_info_t *info; |
2565 | 960 | dtbl_entry_t *dtbl_entry; |
2566 | | |
2567 | 960 | ws_assert(value); |
2568 | 960 | ws_assert(user_data); |
2569 | | |
2570 | 960 | dtbl_entry = (dtbl_entry_t *)value; |
2571 | 960 | if (dtbl_entry->current == NULL || |
2572 | 960 | dtbl_entry->current->protocol == NULL) { |
2573 | | /* |
2574 | | * Either there is no dissector for this entry, or |
2575 | | * the dissector doesn't have a protocol associated |
2576 | | * with it. |
2577 | | * |
2578 | | * XXX - should the latter check be done? |
2579 | | */ |
2580 | 0 | return; |
2581 | 0 | } |
2582 | | |
2583 | 960 | info = (dissector_foreach_info_t *)user_data; |
2584 | 960 | info->caller_func(info->table_name, info->selector_type, key, value, |
2585 | 960 | info->caller_data); |
2586 | 960 | } |
2587 | | |
2588 | | /* |
2589 | | * Called for each entry in the table of all dissector tables. |
2590 | | */ |
2591 | | static void |
2592 | | dissector_all_tables_foreach_func (void *key, void *value, void *user_data) |
2593 | 9.69k | { |
2594 | 9.69k | dissector_table_t sub_dissectors; |
2595 | 9.69k | dissector_foreach_info_t *info; |
2596 | | |
2597 | 9.69k | ws_assert(value); |
2598 | 9.69k | ws_assert(user_data); |
2599 | | |
2600 | 9.69k | sub_dissectors = (dissector_table_t)value; |
2601 | 9.69k | info = (dissector_foreach_info_t *)user_data; |
2602 | 9.69k | info->table_name = (char*) key; |
2603 | 9.69k | info->selector_type = get_dissector_table_selector_type(info->table_name); |
2604 | 9.69k | g_hash_table_foreach(sub_dissectors->hash_table, info->next_func, info); |
2605 | 9.69k | } |
2606 | | |
2607 | | #if 0 |
2608 | | /* |
2609 | | * Walk all dissector tables calling a user supplied function on each |
2610 | | * entry. |
2611 | | */ |
2612 | | static void |
2613 | | dissector_all_tables_foreach (DATFunc func, |
2614 | | void *user_data) |
2615 | | { |
2616 | | dissector_foreach_info_t info; |
2617 | | |
2618 | | info.caller_data = user_data; |
2619 | | info.caller_func = func; |
2620 | | info.next_func = dissector_table_foreach_func; |
2621 | | g_hash_table_foreach(dissector_tables, dissector_all_tables_foreach_func, &info); |
2622 | | } |
2623 | | #endif |
2624 | | |
2625 | | /* |
2626 | | * Walk one dissector table's hash table calling a user supplied function |
2627 | | * on each entry. |
2628 | | */ |
2629 | | void |
2630 | | dissector_table_foreach (const char *table_name, |
2631 | | DATFunc func, |
2632 | | void * user_data) |
2633 | 16 | { |
2634 | 16 | dissector_foreach_info_t info; |
2635 | 16 | dissector_table_t sub_dissectors = find_dissector_table(table_name); |
2636 | | |
2637 | 16 | info.table_name = table_name; |
2638 | 16 | info.selector_type = sub_dissectors->type; |
2639 | 16 | info.caller_func = func; |
2640 | 16 | info.caller_data = user_data; |
2641 | 16 | g_hash_table_foreach(sub_dissectors->hash_table, dissector_table_foreach_func, &info); |
2642 | 16 | } |
2643 | | |
2644 | | /* |
2645 | | * Walk one dissector table's list of handles calling a user supplied |
2646 | | * function on each entry. |
2647 | | */ |
2648 | | void |
2649 | | dissector_table_foreach_handle(const char *table_name, |
2650 | | DATFunc_handle func, |
2651 | | void * user_data) |
2652 | 0 | { |
2653 | 0 | dissector_table_t sub_dissectors = find_dissector_table(table_name); |
2654 | 0 | GSList *tmp; |
2655 | |
|
2656 | 0 | for (tmp = sub_dissectors->dissector_handles; tmp != NULL; |
2657 | 0 | tmp = g_slist_next(tmp)) |
2658 | 0 | func(table_name, tmp->data, user_data); |
2659 | 0 | } |
2660 | | |
2661 | | /* |
2662 | | * Called for each entry in a dissector table. |
2663 | | */ |
2664 | | static void |
2665 | | dissector_table_foreach_changed_func (void *key, void *value, void *user_data) |
2666 | 254k | { |
2667 | 254k | dtbl_entry_t *dtbl_entry; |
2668 | 254k | dissector_foreach_info_t *info; |
2669 | | |
2670 | 254k | ws_assert(value); |
2671 | 254k | ws_assert(user_data); |
2672 | | |
2673 | 254k | dtbl_entry = (dtbl_entry_t *)value; |
2674 | 254k | if (dtbl_entry->initial == dtbl_entry->current) { |
2675 | | /* |
2676 | | * Entry hasn't changed - don't call the function. |
2677 | | */ |
2678 | 254k | return; |
2679 | 254k | } |
2680 | | |
2681 | 0 | info = (dissector_foreach_info_t *)user_data; |
2682 | 0 | info->caller_func(info->table_name, info->selector_type, key, value, |
2683 | 0 | info->caller_data); |
2684 | 0 | } |
2685 | | |
2686 | | /* |
2687 | | * Walk all dissector tables calling a user supplied function only on |
2688 | | * any entry that has been changed from its original state. |
2689 | | */ |
2690 | | void |
2691 | | dissector_all_tables_foreach_changed (DATFunc func, |
2692 | | void *user_data) |
2693 | 16 | { |
2694 | 16 | dissector_foreach_info_t info; |
2695 | | |
2696 | 16 | info.caller_data = user_data; |
2697 | 16 | info.caller_func = func; |
2698 | 16 | info.next_func = dissector_table_foreach_changed_func; |
2699 | 16 | g_hash_table_foreach(dissector_tables, dissector_all_tables_foreach_func, &info); |
2700 | 16 | } |
2701 | | |
2702 | | /* |
2703 | | * Walk one dissector table calling a user supplied function only on |
2704 | | * any entry that has been changed from its original state. |
2705 | | */ |
2706 | | void |
2707 | | dissector_table_foreach_changed (const char *table_name, |
2708 | | DATFunc func, |
2709 | | void * user_data) |
2710 | 0 | { |
2711 | 0 | dissector_foreach_info_t info; |
2712 | 0 | dissector_table_t sub_dissectors = find_dissector_table(table_name); |
2713 | |
|
2714 | 0 | info.table_name = table_name; |
2715 | 0 | info.selector_type = sub_dissectors->type; |
2716 | 0 | info.caller_func = func; |
2717 | 0 | info.caller_data = user_data; |
2718 | 0 | g_hash_table_foreach(sub_dissectors->hash_table, |
2719 | 0 | dissector_table_foreach_changed_func, &info); |
2720 | 0 | } |
2721 | | |
2722 | | typedef struct dissector_foreach_table_info { |
2723 | | void * caller_data; |
2724 | | DATFunc_table caller_func; |
2725 | | } dissector_foreach_table_info_t; |
2726 | | |
2727 | | /* |
2728 | | * Called for each entry in the table of all dissector tables. |
2729 | | * This is used if we directly process the hash table. |
2730 | | */ |
2731 | | static void |
2732 | | dissector_all_tables_foreach_table_func (void *key, void *value, void *user_data) |
2733 | 9.69k | { |
2734 | 9.69k | dissector_table_t table; |
2735 | 9.69k | dissector_foreach_table_info_t *info; |
2736 | | |
2737 | 9.69k | table = (dissector_table_t)value; |
2738 | 9.69k | info = (dissector_foreach_table_info_t *)user_data; |
2739 | 9.69k | (*info->caller_func)((char *)key, table->ui_name, info->caller_data); |
2740 | 9.69k | } |
2741 | | |
2742 | | /* |
2743 | | * Called for each key in the table of all dissector tables. |
2744 | | * This is used if we get a list of table names, sort it, and process the list. |
2745 | | */ |
2746 | | static void |
2747 | | dissector_all_tables_foreach_list_func (void *key, void *user_data) |
2748 | 0 | { |
2749 | 0 | dissector_table_t table; |
2750 | 0 | dissector_foreach_table_info_t *info; |
2751 | |
|
2752 | 0 | table = (dissector_table_t)g_hash_table_lookup(dissector_tables, key); |
2753 | 0 | info = (dissector_foreach_table_info_t *)user_data; |
2754 | 0 | (*info->caller_func)((char*)key, table->ui_name, info->caller_data); |
2755 | 0 | } |
2756 | | |
2757 | | /* |
2758 | | * Walk all dissector tables calling a user supplied function on each |
2759 | | * table. |
2760 | | */ |
2761 | | void |
2762 | | dissector_all_tables_foreach_table (DATFunc_table func, |
2763 | | void * user_data, |
2764 | | GCompareFunc compare_key_func) |
2765 | 16 | { |
2766 | 16 | dissector_foreach_table_info_t info; |
2767 | 16 | GList *list; |
2768 | | |
2769 | 16 | info.caller_data = user_data; |
2770 | 16 | info.caller_func = func; |
2771 | 16 | if (compare_key_func != NULL) |
2772 | 0 | { |
2773 | 0 | list = g_hash_table_get_keys(dissector_tables); |
2774 | 0 | list = g_list_sort(list, compare_key_func); |
2775 | 0 | g_list_foreach(list, dissector_all_tables_foreach_list_func, &info); |
2776 | 0 | g_list_free(list); |
2777 | 0 | } |
2778 | 16 | else |
2779 | 16 | { |
2780 | 16 | g_hash_table_foreach(dissector_tables, dissector_all_tables_foreach_table_func, &info); |
2781 | 16 | } |
2782 | 16 | } |
2783 | | |
2784 | | dissector_table_t |
2785 | | register_dissector_table(const char *name, const char *ui_name, const int proto, const ftenum_t type, |
2786 | | const int param) |
2787 | 9.52k | { |
2788 | 9.52k | dissector_table_t sub_dissectors; |
2789 | | |
2790 | | /* Create and register the dissector table for this name; returns */ |
2791 | | /* a pointer to the dissector table. */ |
2792 | 9.52k | sub_dissectors = g_slice_new(struct dissector_table); |
2793 | 9.52k | switch (type) { |
2794 | | |
2795 | 2.51k | case FT_UINT8: |
2796 | 4.20k | case FT_UINT16: |
2797 | 4.40k | case FT_UINT24: |
2798 | 7.92k | case FT_UINT32: |
2799 | | /* |
2800 | | * XXX - there's no "g_uint_hash()" or "g_uint_equal()", |
2801 | | * so we use "g_direct_hash()" and "g_direct_equal()". |
2802 | | */ |
2803 | 7.92k | sub_dissectors->hash_table = g_hash_table_new_full(g_direct_hash, |
2804 | 7.92k | g_direct_equal, |
2805 | 7.92k | NULL, |
2806 | 7.92k | &g_free); |
2807 | 7.92k | break; |
2808 | | |
2809 | 1.13k | case FT_STRING: |
2810 | 1.15k | case FT_STRINGZ: |
2811 | 1.15k | case FT_STRINGZPAD: |
2812 | 1.15k | case FT_STRINGZTRUNC: |
2813 | 1.15k | sub_dissectors->hash_table = g_hash_table_new_full(g_str_hash, |
2814 | 1.15k | g_str_equal, |
2815 | 1.15k | &g_free, |
2816 | 1.15k | &g_free); |
2817 | 1.15k | break; |
2818 | 32 | case FT_GUID: |
2819 | 32 | sub_dissectors->hash_table = g_hash_table_new_full(uuid_hash, |
2820 | 32 | uuid_equal, |
2821 | 32 | NULL, |
2822 | 32 | &g_free); |
2823 | 32 | break; |
2824 | | |
2825 | 416 | case FT_NONE: |
2826 | | /* Dissector tables with FT_NONE don't have values associated with |
2827 | | dissectors so this will always be a hash table size of 1 just |
2828 | | to store the single dtbl_entry_t */ |
2829 | 416 | sub_dissectors->hash_table = g_hash_table_new_full(g_direct_hash, |
2830 | 416 | g_direct_equal, |
2831 | 416 | NULL, |
2832 | 416 | &g_free); |
2833 | 416 | break; |
2834 | | |
2835 | 0 | default: |
2836 | 0 | ws_error("The dissector table %s (%s) is registering an unsupported type - are you using a buggy plugin?", name, ui_name); |
2837 | 0 | ws_assert_not_reached(); |
2838 | 9.52k | } |
2839 | 9.52k | sub_dissectors->dissector_handles = NULL; |
2840 | 9.52k | sub_dissectors->da_descriptions = NULL; |
2841 | 9.52k | sub_dissectors->ui_name = ui_name; |
2842 | 9.52k | sub_dissectors->type = type; |
2843 | 9.52k | sub_dissectors->param = param; |
2844 | 9.52k | sub_dissectors->protocol = (proto == -1) ? NULL : find_protocol_by_id(proto); |
2845 | | /* Make sure the registration is unique */ |
2846 | 9.52k | if (!g_hash_table_insert(dissector_tables, (void *)name, (void *) sub_dissectors)) { |
2847 | 0 | ws_error("The dissector table %s (%s) is already registered - are you using a buggy plugin?", name, ui_name); |
2848 | 0 | } |
2849 | 9.52k | return sub_dissectors; |
2850 | 9.52k | } |
2851 | | |
2852 | | dissector_table_t register_custom_dissector_table(const char *name, |
2853 | | const char *ui_name, const int proto, GHashFunc hash_func, GEqualFunc key_equal_func, |
2854 | | GDestroyNotify key_destroy_func) |
2855 | 176 | { |
2856 | 176 | dissector_table_t sub_dissectors; |
2857 | | |
2858 | | /* Create and register the dissector table for this name; returns */ |
2859 | | /* a pointer to the dissector table. */ |
2860 | 176 | sub_dissectors = g_slice_new(struct dissector_table); |
2861 | 176 | sub_dissectors->hash_table = g_hash_table_new_full(hash_func, |
2862 | 176 | key_equal_func, |
2863 | 176 | key_destroy_func, |
2864 | 176 | &g_free); |
2865 | | |
2866 | 176 | sub_dissectors->dissector_handles = NULL; |
2867 | 176 | sub_dissectors->da_descriptions = NULL; |
2868 | 176 | sub_dissectors->ui_name = ui_name; |
2869 | 176 | sub_dissectors->type = FT_BYTES; /* Consider key a "blob" of data, no need to really create new type */ |
2870 | 176 | sub_dissectors->param = BASE_NONE; |
2871 | 176 | sub_dissectors->protocol = (proto == -1) ? NULL : find_protocol_by_id(proto); |
2872 | | /* Make sure the registration is unique */ |
2873 | 176 | if (!g_hash_table_insert(dissector_tables, (void *)name, (void *) sub_dissectors)) { |
2874 | 0 | ws_error("The dissector table %s (%s) is already registered - are you using a buggy plugin?", name, ui_name); |
2875 | 0 | } |
2876 | 176 | return sub_dissectors; |
2877 | 176 | } |
2878 | | |
2879 | | void |
2880 | 48 | register_dissector_table_alias(dissector_table_t dissector_table, const char *alias_name) { |
2881 | 48 | if (!dissector_table || !alias_name) return; |
2882 | | |
2883 | 32 | const char *name = NULL; |
2884 | 32 | GList *list = g_hash_table_get_keys(dissector_tables); |
2885 | 6.46k | for (GList *cur = list; cur; cur = cur->next) { |
2886 | 6.46k | if (g_hash_table_lookup(dissector_tables, cur->data) == dissector_table) { |
2887 | 32 | name = (const char *) cur->data; |
2888 | 32 | break; |
2889 | 32 | } |
2890 | 6.46k | } |
2891 | 32 | g_list_free(list); |
2892 | 32 | if (!name) return; |
2893 | | |
2894 | 32 | g_hash_table_insert(dissector_table_aliases, (void *) alias_name, (void *) name); |
2895 | 32 | } |
2896 | | |
2897 | | void |
2898 | | deregister_dissector_table(const char *name) |
2899 | 0 | { |
2900 | 0 | dissector_table_t sub_dissectors = (dissector_table_t) g_hash_table_lookup(dissector_tables, name); |
2901 | 0 | if (!sub_dissectors) return; |
2902 | | |
2903 | 0 | g_hash_table_remove(dissector_tables, name); |
2904 | |
|
2905 | 0 | GList *list = g_hash_table_get_keys(dissector_table_aliases); |
2906 | 0 | for (GList *cur = list; cur; cur = cur->next) { |
2907 | 0 | void *alias_name = cur->data; |
2908 | 0 | if (g_hash_table_lookup(dissector_table_aliases, alias_name) == name) { |
2909 | 0 | g_hash_table_remove(dissector_table_aliases, alias_name); |
2910 | 0 | } |
2911 | 0 | } |
2912 | 0 | g_list_free(list); |
2913 | 0 | } |
2914 | | |
2915 | | const char * |
2916 | | get_dissector_table_ui_name(const char *name) |
2917 | 0 | { |
2918 | 0 | dissector_table_t sub_dissectors = find_dissector_table(name); |
2919 | 0 | if (!sub_dissectors) return NULL; |
2920 | | |
2921 | 0 | return sub_dissectors->ui_name; |
2922 | 0 | } |
2923 | | |
2924 | | ftenum_t |
2925 | | get_dissector_table_selector_type(const char *name) |
2926 | 9.69k | { |
2927 | 9.69k | dissector_table_t sub_dissectors = find_dissector_table(name); |
2928 | 9.69k | if (!sub_dissectors) return FT_NONE; |
2929 | | |
2930 | 9.69k | return sub_dissectors->type; |
2931 | 9.69k | } |
2932 | | |
2933 | | int |
2934 | | get_dissector_table_param(const char *name) |
2935 | 0 | { |
2936 | 0 | dissector_table_t sub_dissectors = find_dissector_table(name); |
2937 | 0 | if (!sub_dissectors) return 0; |
2938 | | |
2939 | 0 | return sub_dissectors->param; |
2940 | 0 | } |
2941 | | |
2942 | | static void |
2943 | | check_valid_heur_name_or_fail(const char *heur_name) |
2944 | 7.15k | { |
2945 | 7.15k | if (proto_check_field_name_lower(heur_name)) { |
2946 | 0 | ws_error("Heuristic Protocol internal name \"%s\" has one or more invalid characters." |
2947 | 0 | " Allowed are lowercase, digits, '-', '_' and non-repeating '.'." |
2948 | 0 | " This might be caused by an inappropriate plugin or a development error.", heur_name); |
2949 | 0 | } |
2950 | 7.15k | } |
2951 | | |
2952 | | /* Finds a heuristic dissector table by table name. */ |
2953 | | heur_dissector_list_t |
2954 | | find_heur_dissector_list(const char *name) |
2955 | 7.20k | { |
2956 | 7.20k | return (heur_dissector_list_t)g_hash_table_lookup(heur_dissector_lists, name); |
2957 | 7.20k | } |
2958 | | |
2959 | | bool |
2960 | 0 | has_heur_dissector_list(const char *name) { |
2961 | 0 | return (find_heur_dissector_list(name) != NULL); |
2962 | 0 | } |
2963 | | |
2964 | | heur_dtbl_entry_t* find_heur_dissector_by_unique_short_name(const char *short_name) |
2965 | 7.18k | { |
2966 | 7.18k | return (heur_dtbl_entry_t*)g_hash_table_lookup(heuristic_short_names, short_name); |
2967 | 7.18k | } |
2968 | | |
2969 | | void |
2970 | | heur_dissector_add(const char *name, heur_dissector_t dissector, const char *display_name, const char *internal_name, const int proto, heuristic_enable_e enable) |
2971 | 7.15k | { |
2972 | 7.15k | heur_dissector_list_t sub_dissectors = find_heur_dissector_list(name); |
2973 | 7.15k | const char *proto_name; |
2974 | 7.15k | heur_dtbl_entry_t *hdtbl_entry; |
2975 | 7.15k | GSList *list_entry; |
2976 | | |
2977 | | /* |
2978 | | * Make sure the dissector table exists. |
2979 | | */ |
2980 | 7.15k | if (sub_dissectors == NULL) { |
2981 | 0 | fprintf(stderr, "OOPS: dissector table \"%s\" doesn't exist\n", |
2982 | 0 | name); |
2983 | 0 | proto_name = proto_get_protocol_name(proto); |
2984 | 0 | if (proto_name != NULL) { |
2985 | 0 | fprintf(stderr, "Protocol being registered is \"%s\"\n", |
2986 | 0 | proto_name); |
2987 | 0 | } |
2988 | 0 | if (wireshark_abort_on_dissector_bug) |
2989 | 0 | abort(); |
2990 | 0 | return; |
2991 | 0 | } |
2992 | | |
2993 | | /* Verify that sub-dissector is not already in the list */ |
2994 | 7.15k | for (list_entry = sub_dissectors->dissectors; |
2995 | 195k | list_entry != NULL; list_entry = list_entry->next) |
2996 | 188k | { |
2997 | 188k | hdtbl_entry = (heur_dtbl_entry_t *)list_entry->data; |
2998 | 188k | if ((hdtbl_entry->dissector == dissector) && |
2999 | 0 | (hdtbl_entry->protocol == find_protocol_by_id(proto))) |
3000 | 0 | { |
3001 | 0 | proto_name = proto_get_protocol_name(proto); |
3002 | 0 | if (proto_name != NULL) { |
3003 | 0 | fprintf(stderr, "Protocol %s is already registered in \"%s\" table\n", |
3004 | 0 | proto_name, name); |
3005 | 0 | } |
3006 | 0 | if (wireshark_abort_on_dissector_bug) |
3007 | 0 | abort(); |
3008 | 0 | return; |
3009 | 0 | } |
3010 | 188k | } |
3011 | | |
3012 | | /* Make sure short_name is "parsing friendly" since it should only be used internally */ |
3013 | 7.15k | check_valid_heur_name_or_fail(internal_name); |
3014 | | |
3015 | 7.15k | hdtbl_entry = g_slice_new(heur_dtbl_entry_t); |
3016 | 7.15k | hdtbl_entry->dissector = dissector; |
3017 | 7.15k | hdtbl_entry->protocol = find_protocol_by_id(proto); |
3018 | 7.15k | hdtbl_entry->display_name = display_name; |
3019 | 7.15k | hdtbl_entry->short_name = g_strdup(internal_name); |
3020 | 7.15k | hdtbl_entry->list_name = g_strdup(name); |
3021 | 7.15k | hdtbl_entry->enabled = (enable == HEURISTIC_ENABLE); |
3022 | 7.15k | hdtbl_entry->enabled_by_default = (enable == HEURISTIC_ENABLE); |
3023 | | |
3024 | | /* do the table insertion */ |
3025 | | /* Ensure short_name is unique */ |
3026 | 7.15k | if (!g_hash_table_insert(heuristic_short_names, (void *)hdtbl_entry->short_name, hdtbl_entry)) { |
3027 | 0 | ws_error("Duplicate heuristic short_name \"%s\"." |
3028 | 0 | " This might be caused by an inappropriate plugin or a development error.", internal_name); |
3029 | 0 | } |
3030 | | |
3031 | 7.15k | sub_dissectors->dissectors = g_slist_prepend(sub_dissectors->dissectors, |
3032 | 7.15k | (void *)hdtbl_entry); |
3033 | | |
3034 | | /* XXX - could be optimized to pass hdtbl_entry directly */ |
3035 | 7.15k | proto_add_heuristic_dissector(hdtbl_entry->protocol, hdtbl_entry->short_name); |
3036 | | |
3037 | | /* Add the dissector as a dependency |
3038 | | (some heuristic tables don't have protocol association, so there is |
3039 | | the need for the NULL check */ |
3040 | 7.15k | if (sub_dissectors->protocol != NULL) |
3041 | 7.15k | register_depend_dissector(proto_get_protocol_short_name(sub_dissectors->protocol), proto_get_protocol_short_name(hdtbl_entry->protocol)); |
3042 | 7.15k | } |
3043 | | |
3044 | | |
3045 | | |
3046 | | static int |
3047 | 16 | find_matching_heur_dissector(const void *a, const void *b) { |
3048 | 16 | const heur_dtbl_entry_t *hdtbl_entry_a = (const heur_dtbl_entry_t *) a; |
3049 | 16 | const heur_dtbl_entry_t *hdtbl_entry_b = (const heur_dtbl_entry_t *) b; |
3050 | | |
3051 | 16 | return (hdtbl_entry_a->dissector == hdtbl_entry_b->dissector) && |
3052 | 16 | (hdtbl_entry_a->protocol == hdtbl_entry_b->protocol) ? 0 : 1; |
3053 | 16 | } |
3054 | | |
3055 | | void |
3056 | 16 | heur_dissector_delete(const char *name, heur_dissector_t dissector, const int proto) { |
3057 | 16 | heur_dissector_list_t sub_dissectors = find_heur_dissector_list(name); |
3058 | 16 | heur_dtbl_entry_t hdtbl_entry; |
3059 | 16 | GSList *found_entry; |
3060 | | |
3061 | | /* sanity check */ |
3062 | 16 | ws_assert(sub_dissectors != NULL); |
3063 | | |
3064 | 16 | hdtbl_entry.dissector = dissector; |
3065 | 16 | hdtbl_entry.protocol = find_protocol_by_id(proto); |
3066 | | |
3067 | 16 | found_entry = g_slist_find_custom(sub_dissectors->dissectors, |
3068 | 16 | (void *) &hdtbl_entry, find_matching_heur_dissector); |
3069 | | |
3070 | 16 | if (found_entry) { |
3071 | 0 | heur_dtbl_entry_t *found_hdtbl_entry = (heur_dtbl_entry_t *)(found_entry->data); |
3072 | 0 | proto_add_deregistered_data(found_hdtbl_entry->list_name); |
3073 | 0 | g_hash_table_remove(heuristic_short_names, found_hdtbl_entry->short_name); |
3074 | 0 | proto_add_deregistered_data(found_hdtbl_entry->short_name); |
3075 | 0 | proto_add_deregistered_slice(sizeof(heur_dtbl_entry_t), found_hdtbl_entry); |
3076 | 0 | sub_dissectors->dissectors = g_slist_delete_link(sub_dissectors->dissectors, |
3077 | 0 | found_entry); |
3078 | 0 | } |
3079 | 16 | } |
3080 | | |
3081 | | bool |
3082 | | dissector_try_heuristic(heur_dissector_list_t sub_dissectors, tvbuff_t *tvb, |
3083 | | packet_info *pinfo, proto_tree *tree, heur_dtbl_entry_t **heur_dtbl_entry, void *data) |
3084 | 59.5k | { |
3085 | 59.5k | bool status; |
3086 | 59.5k | const char *saved_curr_proto; |
3087 | 59.5k | int saved_proto_layer_num; |
3088 | 59.5k | const char *saved_heur_list_name; |
3089 | 59.5k | GSList *entry; |
3090 | 59.5k | GSList *prev_entry = NULL; |
3091 | 59.5k | uint16_t saved_can_desegment; |
3092 | 59.5k | unsigned saved_layers_len = 0; |
3093 | 59.5k | heur_dtbl_entry_t *hdtbl_entry; |
3094 | 59.5k | int proto_id; |
3095 | 59.5k | int len; |
3096 | 59.5k | bool consumed_none; |
3097 | 59.5k | unsigned saved_desegment_len; |
3098 | 59.5k | unsigned saved_tree_count = tree ? tree->tree_data->count : 0; |
3099 | | |
3100 | | /* can_desegment is set to 2 by anyone which offers this api/service. |
3101 | | then every time a subdissector is called it is decremented by one. |
3102 | | thus only the subdissector immediately on top of whoever offers this |
3103 | | service can use it. |
3104 | | We save the current value of "can_desegment" for the |
3105 | | benefit of TCP proxying dissectors such as SOCKS, so they |
3106 | | can restore it and allow the dissectors they call to use |
3107 | | the desegmentation service. |
3108 | | */ |
3109 | 59.5k | saved_can_desegment = pinfo->can_desegment; |
3110 | 59.5k | pinfo->saved_can_desegment = saved_can_desegment; |
3111 | 59.5k | pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0); |
3112 | | |
3113 | 59.5k | status = false; |
3114 | 59.5k | saved_curr_proto = pinfo->current_proto; |
3115 | 59.5k | saved_proto_layer_num = pinfo->curr_proto_layer_num; |
3116 | 59.5k | saved_heur_list_name = pinfo->heur_list_name; |
3117 | | |
3118 | 59.5k | saved_layers_len = wmem_list_count(pinfo->layers); |
3119 | 59.5k | *heur_dtbl_entry = NULL; |
3120 | | |
3121 | 59.5k | DISSECTOR_ASSERT(saved_layers_len < prefs.gui_max_tree_depth); |
3122 | | |
3123 | 602k | for (entry = sub_dissectors->dissectors; entry != NULL; |
3124 | 552k | entry = g_slist_next(entry)) { |
3125 | | /* XXX - why set this now and above? */ |
3126 | 552k | pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0); |
3127 | 552k | hdtbl_entry = (heur_dtbl_entry_t *)entry->data; |
3128 | | |
3129 | 552k | if (hdtbl_entry->protocol != NULL && |
3130 | 552k | (!proto_is_protocol_enabled(hdtbl_entry->protocol)||(hdtbl_entry->enabled==false))) { |
3131 | | /* |
3132 | | * No - don't try this dissector. |
3133 | | */ |
3134 | 116k | continue; |
3135 | 116k | } |
3136 | | |
3137 | 435k | if (hdtbl_entry->protocol != NULL) { |
3138 | 435k | proto_id = proto_get_id(hdtbl_entry->protocol); |
3139 | | /* do NOT change this behavior - wslua uses the protocol short name set here in order |
3140 | | to determine which Lua-based heuristic dissector to call */ |
3141 | 435k | pinfo->current_proto = |
3142 | 435k | proto_get_protocol_short_name(hdtbl_entry->protocol); |
3143 | | |
3144 | | /* |
3145 | | * Add the protocol name to the layers; we'll remove it |
3146 | | * if the dissector fails. |
3147 | | */ |
3148 | 435k | add_layer(pinfo, proto_id); |
3149 | 435k | } |
3150 | | |
3151 | 435k | pinfo->heur_list_name = hdtbl_entry->list_name; |
3152 | | |
3153 | 435k | saved_desegment_len = pinfo->desegment_len; |
3154 | 435k | len = (hdtbl_entry->dissector)(tvb, pinfo, tree, data); |
3155 | 435k | consumed_none = len == 0 || (pinfo->desegment_len != saved_desegment_len && pinfo->desegment_offset == 0); |
3156 | 435k | if (hdtbl_entry->protocol != NULL && |
3157 | 425k | (consumed_none || (tree && saved_tree_count == tree->tree_data->count))) { |
3158 | | /* |
3159 | | * We added a protocol layer above. The dissector |
3160 | | * didn't consume any data or it didn't add any |
3161 | | * items to the tree so remove it from the list. |
3162 | | */ |
3163 | 831k | while (wmem_list_count(pinfo->layers) > saved_layers_len) { |
3164 | | /* |
3165 | | * Only reduce the layer number if the dissector |
3166 | | * didn't consume data. Since tree can be NULL on |
3167 | | * the first pass, we cannot check it or it will |
3168 | | * break dissectors that rely on a stable value. |
3169 | | */ |
3170 | 415k | remove_last_layer(pinfo, consumed_none); |
3171 | 415k | } |
3172 | 415k | } |
3173 | 435k | if (len) { |
3174 | 9.42k | if (ws_log_msg_is_active(WS_LOG_DOMAIN, LOG_LEVEL_DEBUG)) { |
3175 | 0 | ws_debug("Frame: %d | Layers: %s | Dissector: %s\n", pinfo->num, proto_list_layers(pinfo), hdtbl_entry->short_name); |
3176 | 0 | } |
3177 | | |
3178 | 9.42k | *heur_dtbl_entry = hdtbl_entry; |
3179 | | |
3180 | | /* Bubble the matched entry to the top for faster search next time. */ |
3181 | 9.42k | if (prev_entry != NULL) { |
3182 | 4.62k | sub_dissectors->dissectors = g_slist_remove_link(sub_dissectors->dissectors, entry); |
3183 | 4.62k | sub_dissectors->dissectors = g_slist_concat(entry, sub_dissectors->dissectors); |
3184 | 4.62k | } |
3185 | 9.42k | status = true; |
3186 | 9.42k | break; |
3187 | 9.42k | } |
3188 | 425k | prev_entry = entry; |
3189 | 425k | } |
3190 | | |
3191 | 59.5k | pinfo->current_proto = saved_curr_proto; |
3192 | 59.5k | pinfo->curr_proto_layer_num = saved_proto_layer_num; |
3193 | 59.5k | pinfo->heur_list_name = saved_heur_list_name; |
3194 | 59.5k | pinfo->can_desegment = saved_can_desegment; |
3195 | 59.5k | return status; |
3196 | 59.5k | } |
3197 | | |
3198 | | typedef struct heur_dissector_foreach_info { |
3199 | | void * caller_data; |
3200 | | DATFunc_heur caller_func; |
3201 | | GHFunc next_func; |
3202 | | const char *table_name; |
3203 | | } heur_dissector_foreach_info_t; |
3204 | | |
3205 | | /* |
3206 | | * Called for each entry in a heuristic dissector table. |
3207 | | */ |
3208 | | static void |
3209 | | heur_dissector_table_foreach_func (void *data, void *user_data) |
3210 | 0 | { |
3211 | 0 | heur_dissector_foreach_info_t *info; |
3212 | |
|
3213 | 0 | ws_assert(data); |
3214 | 0 | ws_assert(user_data); |
3215 | |
|
3216 | 0 | info = (heur_dissector_foreach_info_t *)user_data; |
3217 | 0 | info->caller_func(info->table_name, (heur_dtbl_entry_t *)data, |
3218 | 0 | info->caller_data); |
3219 | 0 | } |
3220 | | |
3221 | | /* |
3222 | | * Walk one heuristic dissector table's list calling a user supplied function |
3223 | | * on each entry. |
3224 | | */ |
3225 | | void |
3226 | | heur_dissector_table_foreach (const char *table_name, |
3227 | | DATFunc_heur func, |
3228 | | void * user_data) |
3229 | 0 | { |
3230 | 0 | heur_dissector_foreach_info_t info; |
3231 | 0 | heur_dissector_list_t sub_dissectors = find_heur_dissector_list(table_name); |
3232 | 0 | DISSECTOR_ASSERT(sub_dissectors != NULL); |
3233 | |
|
3234 | 0 | info.table_name = table_name; |
3235 | 0 | info.caller_func = func; |
3236 | 0 | info.caller_data = user_data; |
3237 | 0 | g_slist_foreach(sub_dissectors->dissectors, |
3238 | 0 | heur_dissector_table_foreach_func, &info); |
3239 | 0 | } |
3240 | | |
3241 | | /* |
3242 | | * Called for each entry in the table of all heuristic dissector tables. |
3243 | | */ |
3244 | | typedef struct heur_dissector_foreach_table_info { |
3245 | | void * caller_data; |
3246 | | DATFunc_heur_table caller_func; |
3247 | | } heur_dissector_foreach_table_info_t; |
3248 | | |
3249 | | /* |
3250 | | * Called for each entry in the table of all heuristic dissector tables. |
3251 | | * This is used if we directly process the hash table. |
3252 | | */ |
3253 | | static void |
3254 | | dissector_all_heur_tables_foreach_table_func (void *key, void *value, void *user_data) |
3255 | 0 | { |
3256 | 0 | heur_dissector_foreach_table_info_t *info; |
3257 | |
|
3258 | 0 | info = (heur_dissector_foreach_table_info_t *)user_data; |
3259 | 0 | (*info->caller_func)((char *)key, (struct heur_dissector_list *)value, info->caller_data); |
3260 | 0 | } |
3261 | | |
3262 | | /* |
3263 | | * Called for each key in the table of all dissector tables. |
3264 | | * This is used if we get a list of table names, sort it, and process the list. |
3265 | | */ |
3266 | | static void |
3267 | | dissector_all_heur_tables_foreach_list_func (void *key, void *user_data) |
3268 | 0 | { |
3269 | 0 | struct heur_dissector_list *list; |
3270 | 0 | heur_dissector_foreach_table_info_t *info; |
3271 | |
|
3272 | 0 | list = (struct heur_dissector_list *)g_hash_table_lookup(heur_dissector_lists, key); |
3273 | 0 | info = (heur_dissector_foreach_table_info_t *)user_data; |
3274 | 0 | (*info->caller_func)((char*)key, list, info->caller_data); |
3275 | 0 | } |
3276 | | |
3277 | | /* |
3278 | | * Walk all heuristic dissector tables calling a user supplied function on each |
3279 | | * table. |
3280 | | */ |
3281 | | void |
3282 | | dissector_all_heur_tables_foreach_table (DATFunc_heur_table func, |
3283 | | void * user_data, |
3284 | | GCompareFunc compare_key_func) |
3285 | 0 | { |
3286 | 0 | heur_dissector_foreach_table_info_t info; |
3287 | 0 | GList *list; |
3288 | |
|
3289 | 0 | info.caller_data = user_data; |
3290 | 0 | info.caller_func = func; |
3291 | 0 | if (compare_key_func != NULL) |
3292 | 0 | { |
3293 | 0 | list = g_hash_table_get_keys(dissector_tables); |
3294 | 0 | list = g_list_sort(list, compare_key_func); |
3295 | 0 | g_list_foreach(list, dissector_all_heur_tables_foreach_list_func, &info); |
3296 | 0 | g_list_free(list); |
3297 | 0 | } |
3298 | 0 | else |
3299 | 0 | { |
3300 | 0 | g_hash_table_foreach(heur_dissector_lists, dissector_all_heur_tables_foreach_table_func, &info); |
3301 | 0 | } |
3302 | 0 | } |
3303 | | |
3304 | | static void |
3305 | | display_heur_dissector_table_entries(const char *table_name, |
3306 | | heur_dtbl_entry_t *hdtbl_entry, void *user_data _U_) |
3307 | 0 | { |
3308 | 0 | if (hdtbl_entry->protocol != NULL) { |
3309 | 0 | printf("%s\t%s\t%c\t%c\t%s\t%s\n", |
3310 | 0 | table_name, |
3311 | 0 | proto_get_protocol_filter_name(proto_get_id(hdtbl_entry->protocol)), |
3312 | 0 | (proto_is_protocol_enabled(hdtbl_entry->protocol) && hdtbl_entry->enabled) ? 'T' : 'F', |
3313 | 0 | (proto_is_protocol_enabled_by_default(hdtbl_entry->protocol) && hdtbl_entry->enabled_by_default) ? 'T' : 'F', |
3314 | 0 | hdtbl_entry->short_name, |
3315 | 0 | hdtbl_entry->display_name); |
3316 | 0 | } |
3317 | 0 | } |
3318 | | |
3319 | | static void |
3320 | | dissector_dump_heur_decodes_display(const char *table_name, struct heur_dissector_list *listptr _U_, void *user_data _U_) |
3321 | 0 | { |
3322 | 0 | heur_dissector_table_foreach(table_name, display_heur_dissector_table_entries, NULL); |
3323 | 0 | } |
3324 | | |
3325 | | /* |
3326 | | * For each heuristic dissector table, dump list of dissectors (filter_names) for that table |
3327 | | */ |
3328 | | void |
3329 | | dissector_dump_heur_decodes(void) |
3330 | 0 | { |
3331 | 0 | dissector_all_heur_tables_foreach_table(dissector_dump_heur_decodes_display, NULL, NULL); |
3332 | 0 | } |
3333 | | |
3334 | | |
3335 | | heur_dissector_list_t |
3336 | | register_heur_dissector_list_with_description(const char *name, const char *ui_name, const int proto) |
3337 | 1.52k | { |
3338 | 1.52k | heur_dissector_list_t sub_dissectors; |
3339 | | |
3340 | | /* Create and register the dissector table for this name; returns */ |
3341 | | /* a pointer to the dissector table. */ |
3342 | 1.52k | sub_dissectors = g_slice_new(struct heur_dissector_list); |
3343 | 1.52k | sub_dissectors->protocol = (proto == -1) ? NULL : find_protocol_by_id(proto); |
3344 | 1.52k | sub_dissectors->ui_name = ui_name; |
3345 | 1.52k | sub_dissectors->dissectors = NULL; /* initially empty */ |
3346 | | /* Make sure the registration is unique */ |
3347 | 1.52k | if (!g_hash_table_insert(heur_dissector_lists, (void *)name, |
3348 | 1.52k | (void *) sub_dissectors)) { |
3349 | 0 | ws_error("The heuristic dissector list %s is already registered - are you using a buggy plugin?", name); |
3350 | 0 | } |
3351 | 1.52k | return sub_dissectors; |
3352 | 1.52k | } |
3353 | | |
3354 | | heur_dissector_list_t |
3355 | | register_heur_dissector_list(const char *name, const int proto) |
3356 | 32 | { |
3357 | 32 | return register_heur_dissector_list_with_description(name, NULL, proto); |
3358 | 32 | } |
3359 | | |
3360 | | void |
3361 | | deregister_heur_dissector_list(const char *name) |
3362 | 0 | { |
3363 | 0 | heur_dissector_list_t sub_dissectors = find_heur_dissector_list(name); |
3364 | 0 | if (sub_dissectors == NULL) { |
3365 | 0 | return; |
3366 | 0 | } |
3367 | | |
3368 | 0 | g_hash_table_remove(heur_dissector_lists, name); |
3369 | 0 | } |
3370 | | |
3371 | | const char * |
3372 | | heur_dissector_list_get_description(heur_dissector_list_t list) |
3373 | 0 | { |
3374 | 0 | return list ? list->ui_name : NULL; |
3375 | 0 | } |
3376 | | |
3377 | | /* |
3378 | | * Register dissectors by name; used if one dissector always calls a |
3379 | | * particular dissector, or if it bases the decision of which dissector |
3380 | | * to call on something other than a numerical value or on "try a bunch |
3381 | | * of dissectors until one likes the packet". |
3382 | | */ |
3383 | | |
3384 | | /* Get the long name of the protocol for a dissector handle, if it has |
3385 | | a protocol. */ |
3386 | | const char * |
3387 | | dissector_handle_get_protocol_long_name(const dissector_handle_t handle) |
3388 | 77 | { |
3389 | 77 | if (handle == NULL || handle->protocol == NULL) { |
3390 | 0 | return NULL; |
3391 | 0 | } |
3392 | 77 | return proto_get_protocol_long_name(handle->protocol); |
3393 | 77 | } |
3394 | | |
3395 | | /* Get the short name of the protocol for a dissector handle, if it has |
3396 | | a protocol. */ |
3397 | | const char * |
3398 | | dissector_handle_get_protocol_short_name(const dissector_handle_t handle) |
3399 | 34.4k | { |
3400 | 34.4k | if (handle == NULL || handle->protocol == NULL) { |
3401 | 16 | return NULL; |
3402 | 16 | } |
3403 | 34.4k | return proto_get_protocol_short_name(handle->protocol); |
3404 | 34.4k | } |
3405 | | |
3406 | | /* Get the description for what the dissector in the dissector handle |
3407 | | dissects, if it has one. */ |
3408 | | const char * |
3409 | | dissector_handle_get_description(const dissector_handle_t handle) |
3410 | 32.7k | { |
3411 | 32.7k | if (handle == NULL) { |
3412 | 12.0k | return NULL; |
3413 | 12.0k | } |
3414 | 20.6k | return handle->description; |
3415 | 32.7k | } |
3416 | | |
3417 | | /* Get the index of the protocol for a dissector handle, if it has |
3418 | | a protocol. */ |
3419 | | int |
3420 | | dissector_handle_get_protocol_index(const dissector_handle_t handle) |
3421 | 11.0k | { |
3422 | 11.0k | if (handle == NULL || handle->protocol == NULL) { |
3423 | | /* |
3424 | | * No protocol (see, for example, the handle for |
3425 | | * dissecting the set of protocols where the first |
3426 | | * octet of the payload is an OSI network layer protocol |
3427 | | * ID). |
3428 | | */ |
3429 | 4 | return -1; |
3430 | 4 | } |
3431 | 11.0k | return proto_get_id(handle->protocol); |
3432 | 11.0k | } |
3433 | | |
3434 | | /* Get a GList of all registered dissector names. The content of the list |
3435 | | is owned by the hash table and should not be modified or freed. |
3436 | | Use g_list_free() when done using the list. */ |
3437 | | GList* |
3438 | | get_dissector_names(void) |
3439 | 0 | { |
3440 | 0 | if (!registered_dissectors) { |
3441 | 0 | return NULL; |
3442 | 0 | } |
3443 | | |
3444 | 0 | return g_hash_table_get_keys(registered_dissectors); |
3445 | 0 | } |
3446 | | |
3447 | | /* Find a registered dissector by name. */ |
3448 | | dissector_handle_t |
3449 | | find_dissector(const char *name) |
3450 | 10.1k | { |
3451 | 10.1k | return (dissector_handle_t)g_hash_table_lookup(registered_dissectors, name); |
3452 | 10.1k | } |
3453 | | |
3454 | | /** Find a dissector by name and add parent protocol as a dependency*/ |
3455 | | dissector_handle_t find_dissector_add_dependency(const char *name, const int parent_proto) |
3456 | 16.4k | { |
3457 | 16.4k | dissector_handle_t handle = (dissector_handle_t)g_hash_table_lookup(registered_dissectors, name); |
3458 | 16.4k | if ((handle != NULL) && (parent_proto > 0)) |
3459 | 16.1k | { |
3460 | 16.1k | register_depend_dissector(proto_get_protocol_short_name(find_protocol_by_id(parent_proto)), dissector_handle_get_protocol_short_name(handle)); |
3461 | 16.1k | } |
3462 | | |
3463 | 16.4k | return handle; |
3464 | 16.4k | } |
3465 | | |
3466 | | /* Get a dissector name from handle. */ |
3467 | | const char * |
3468 | | dissector_handle_get_dissector_name(const dissector_handle_t handle) |
3469 | 49.7k | { |
3470 | 49.7k | if (handle == NULL) { |
3471 | 9 | return NULL; |
3472 | 9 | } |
3473 | 49.7k | return handle->name; |
3474 | 49.7k | } |
3475 | | |
3476 | | const char * |
3477 | | dissector_handle_get_pref_suffix(const dissector_handle_t handle) |
3478 | 11.6k | { |
3479 | 11.6k | if (handle == NULL) { |
3480 | 0 | return ""; |
3481 | 0 | } |
3482 | 11.6k | return handle->pref_suffix ? handle->pref_suffix : ""; |
3483 | 11.6k | } |
3484 | | |
3485 | | static void |
3486 | | check_valid_dissector_name_or_fail(const char *name) |
3487 | 47.4k | { |
3488 | 47.4k | if (proto_check_field_name(name)) { |
3489 | 0 | ws_error("Dissector name \"%s\" has one or more invalid characters." |
3490 | 0 | " Allowed are letters, digits, '-', '_' and non-repeating '.'." |
3491 | 0 | " This might be caused by an inappropriate plugin or a development error.", name); |
3492 | 0 | } |
3493 | 47.4k | } |
3494 | | |
3495 | | static dissector_handle_t |
3496 | | new_dissector_handle(const int proto, const char *name, const char *description) |
3497 | 232k | { |
3498 | 232k | struct dissector_handle *handle; |
3499 | | |
3500 | | /* Make sure name is "parsing friendly" - descriptions should be |
3501 | | * used for complicated phrases. NULL for anonymous unregistered |
3502 | | * dissectors is allowed; we check for that in various places. |
3503 | | * |
3504 | | * (It might be safer to have a default name used for anonymous |
3505 | | * dissectors rather than NULL checks scattered in the code.) |
3506 | | */ |
3507 | 232k | if (name) { |
3508 | 47.4k | check_valid_dissector_name_or_fail(name); |
3509 | 47.4k | } |
3510 | | |
3511 | 232k | handle = wmem_new(wmem_epan_scope(), struct dissector_handle); |
3512 | 232k | handle->name = name; |
3513 | 232k | handle->description = description; |
3514 | 232k | handle->protocol = find_protocol_by_id(proto); |
3515 | 232k | handle->pref_suffix = NULL; |
3516 | | |
3517 | 232k | if (handle->description == NULL) { |
3518 | | /* |
3519 | | * No description for what this dissector dissects |
3520 | | * was supplied; use the short name for the protocol, |
3521 | | * if we have the protocol. |
3522 | | * |
3523 | | * (We may have no protocol; see, for example, the handle |
3524 | | * for dissecting the set of protocols where the first |
3525 | | * octet of the payload is an OSI network layer protocol |
3526 | | * ID.) |
3527 | | */ |
3528 | 205k | if (handle->protocol != NULL) |
3529 | 199k | handle->description = proto_get_protocol_short_name(handle->protocol); |
3530 | 205k | } else { |
3531 | 27.0k | if (name && g_strcmp0(name, proto_get_protocol_filter_name(proto)) != 0) { |
3532 | 688 | handle->pref_suffix = ascii_strdown_inplace(wmem_strdup_printf(wmem_epan_scope(), ".%s", name)); |
3533 | 688 | char *pos = handle->pref_suffix; |
3534 | 704 | while ((pos = strchr(pos, '-')) != NULL) { |
3535 | 16 | *pos++ = '_'; |
3536 | 16 | } |
3537 | 688 | } |
3538 | 27.0k | } |
3539 | 232k | return handle; |
3540 | 232k | } |
3541 | | |
3542 | | dissector_handle_t |
3543 | | create_dissector_handle_with_name_and_description(dissector_t dissector, |
3544 | | const int proto, |
3545 | | const char* name, |
3546 | | const char* description) |
3547 | 219k | { |
3548 | 219k | dissector_handle_t handle; |
3549 | | |
3550 | 219k | handle = new_dissector_handle(proto, name, description); |
3551 | 219k | handle->dissector_type = DISSECTOR_TYPE_SIMPLE; |
3552 | 219k | handle->dissector_func.dissector_type_simple = dissector; |
3553 | 219k | handle->dissector_data = NULL; |
3554 | 219k | return handle; |
3555 | 219k | } |
3556 | | |
3557 | | dissector_handle_t |
3558 | | create_dissector_handle_with_name(dissector_t dissector, |
3559 | | const int proto, const char* name) |
3560 | 36.0k | { |
3561 | 36.0k | return create_dissector_handle_with_name_and_description(dissector, proto, name, NULL); |
3562 | 36.0k | } |
3563 | | |
3564 | | /* Create an anonymous handle for a new dissector. */ |
3565 | | dissector_handle_t |
3566 | | create_dissector_handle(dissector_t dissector, const int proto) |
3567 | 156k | { |
3568 | 156k | return create_dissector_handle_with_name_and_description(dissector, proto, NULL, NULL); |
3569 | 156k | } |
3570 | | |
3571 | | static dissector_handle_t |
3572 | | create_dissector_handle_with_name_and_data(dissector_cb_t dissector, const int proto, const char *name, void* cb_data) |
3573 | 12.8k | { |
3574 | 12.8k | dissector_handle_t handle; |
3575 | | |
3576 | 12.8k | handle = new_dissector_handle(proto, name, NULL); |
3577 | 12.8k | handle->dissector_type = DISSECTOR_TYPE_CALLBACK; |
3578 | 12.8k | handle->dissector_func.dissector_type_callback = dissector; |
3579 | 12.8k | handle->dissector_data = cb_data; |
3580 | 12.8k | return handle; |
3581 | 12.8k | } |
3582 | | |
3583 | | dissector_handle_t |
3584 | | create_dissector_handle_with_data(dissector_cb_t dissector, const int proto, void* cb_data) |
3585 | 2.49k | { |
3586 | 2.49k | return create_dissector_handle_with_name_and_data(dissector, proto, NULL, cb_data); |
3587 | 2.49k | } |
3588 | | |
3589 | | /* Destroy an anonymous handle for a dissector. */ |
3590 | | static void |
3591 | | destroy_dissector_handle(dissector_handle_t handle) |
3592 | 0 | { |
3593 | 0 | if (handle == NULL) return; |
3594 | | |
3595 | 0 | dissector_delete_from_all_tables(handle); |
3596 | 0 | deregister_postdissector(handle); |
3597 | 0 | if (handle->pref_suffix) { |
3598 | 0 | wmem_free(wmem_epan_scope(), handle->pref_suffix); |
3599 | 0 | } |
3600 | 0 | wmem_free(wmem_epan_scope(), handle); |
3601 | 0 | } |
3602 | | |
3603 | | static dissector_handle_t |
3604 | | register_dissector_handle(const char *name, dissector_handle_t handle) |
3605 | 47.3k | { |
3606 | 47.3k | bool new_entry; |
3607 | | |
3608 | | /* A registered dissector should have a name. */ |
3609 | 47.3k | if (name == NULL || name[0] == '\0') { |
3610 | 0 | ws_error("A registered dissector name cannot be NULL or the empty string." |
3611 | 0 | " Anonymous dissector handles can be created with create_dissector_handle()." |
3612 | 0 | " This might be caused by an inappropriate plugin or a development error."); |
3613 | 0 | } |
3614 | | |
3615 | 47.3k | new_entry = g_hash_table_insert(registered_dissectors, (void *)name, handle); |
3616 | 47.3k | if (!new_entry) { |
3617 | | /* Make sure the registration is unique */ |
3618 | 0 | ws_error("dissector handle name \"%s\" is already registered", name); |
3619 | 0 | } |
3620 | | |
3621 | 47.3k | return handle; |
3622 | 47.3k | } |
3623 | | |
3624 | | /* Register a new dissector by name. */ |
3625 | | dissector_handle_t |
3626 | | register_dissector(const char *name, dissector_t dissector, const int proto) |
3627 | 36.0k | { |
3628 | 36.0k | dissector_handle_t handle; |
3629 | | |
3630 | 36.0k | handle = create_dissector_handle_with_name(dissector, proto, name); |
3631 | | |
3632 | 36.0k | return register_dissector_handle(name, handle); |
3633 | 36.0k | } |
3634 | | |
3635 | | dissector_handle_t |
3636 | | register_dissector_with_description(const char *name, const char *description, dissector_t dissector, const int proto) |
3637 | 896 | { |
3638 | 896 | dissector_handle_t handle; |
3639 | | |
3640 | 896 | handle = create_dissector_handle_with_name_and_description(dissector, proto, name, description); |
3641 | | |
3642 | 896 | return register_dissector_handle(name, handle); |
3643 | 896 | } |
3644 | | |
3645 | | dissector_handle_t |
3646 | | register_dissector_with_data(const char *name, dissector_cb_t dissector, const int proto, void *cb_data) |
3647 | 10.3k | { |
3648 | 10.3k | dissector_handle_t handle; |
3649 | | |
3650 | 10.3k | handle = create_dissector_handle_with_name_and_data(dissector, proto, name, cb_data); |
3651 | | |
3652 | 10.3k | return register_dissector_handle(name, handle); |
3653 | 10.3k | } |
3654 | | |
3655 | | static bool |
3656 | | remove_depend_dissector_from_list(depend_dissector_list_t sub_dissectors, const char *dependent) |
3657 | 0 | { |
3658 | 0 | return g_hash_table_remove(sub_dissectors->dissectors, dependent); |
3659 | 0 | } |
3660 | | |
3661 | | static void |
3662 | | remove_depend_dissector_ghfunc(void *key _U_, void *value, void *user_data) |
3663 | 0 | { |
3664 | 0 | depend_dissector_list_t sub_dissectors = (depend_dissector_list_t) value; |
3665 | 0 | const char *dependent = (const char *)user_data; |
3666 | |
|
3667 | 0 | remove_depend_dissector_from_list(sub_dissectors, dependent); |
3668 | 0 | } |
3669 | | |
3670 | | /* Deregister a dissector by name. */ |
3671 | | void |
3672 | | deregister_dissector(const char *name) |
3673 | 0 | { |
3674 | 0 | dissector_handle_t handle = find_dissector(name); |
3675 | 0 | if (handle == NULL) return; |
3676 | | |
3677 | 0 | g_hash_table_remove(registered_dissectors, name); |
3678 | 0 | g_hash_table_remove(depend_dissector_lists, name); |
3679 | 0 | g_hash_table_foreach(depend_dissector_lists, remove_depend_dissector_ghfunc, (void *)name); |
3680 | |
|
3681 | 0 | destroy_dissector_handle(handle); |
3682 | 0 | } |
3683 | | |
3684 | | /* Call a dissector through a handle but if the dissector rejected it |
3685 | | * return 0. |
3686 | | */ |
3687 | | int |
3688 | | call_dissector_only(dissector_handle_t handle, tvbuff_t *tvb, |
3689 | | packet_info *pinfo, proto_tree *tree, void *data) |
3690 | 1.34M | { |
3691 | 1.34M | int ret; |
3692 | | |
3693 | 1.34M | DISSECTOR_ASSERT(handle != NULL); |
3694 | 1.34M | ret = call_dissector_work(handle, tvb, pinfo, tree, true, data); |
3695 | 1.34M | return ret; |
3696 | 1.34M | } |
3697 | | |
3698 | | /* Call a dissector through a handle and if this fails call the "data" |
3699 | | * dissector. |
3700 | | */ |
3701 | | int |
3702 | | call_dissector_with_data(dissector_handle_t handle, tvbuff_t *tvb, |
3703 | | packet_info *pinfo, proto_tree *tree, void *data) |
3704 | 567k | { |
3705 | 567k | int ret; |
3706 | | |
3707 | 567k | ret = call_dissector_only(handle, tvb, pinfo, tree, data); |
3708 | 567k | if (ret == 0) { |
3709 | | /* |
3710 | | * The protocol was disabled, or the dissector rejected |
3711 | | * it. Just dissect this packet as data. |
3712 | | */ |
3713 | 9.80k | return call_data_dissector(tvb, pinfo, tree); |
3714 | 9.80k | } |
3715 | 558k | return ret; |
3716 | 567k | } |
3717 | | |
3718 | | int |
3719 | | call_dissector(dissector_handle_t handle, tvbuff_t *tvb, |
3720 | | packet_info *pinfo, proto_tree *tree) |
3721 | 313k | { |
3722 | 313k | return call_dissector_with_data(handle, tvb, pinfo, tree, NULL); |
3723 | 313k | } |
3724 | | |
3725 | | int |
3726 | | call_data_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
3727 | 261k | { |
3728 | 261k | DISSECTOR_ASSERT(data_handle->protocol != NULL); |
3729 | 261k | return call_dissector_work(data_handle, tvb, pinfo, tree, true, NULL); |
3730 | 261k | } |
3731 | | |
3732 | | /* |
3733 | | * Call a heuristic dissector through a heur_dtbl_entry |
3734 | | */ |
3735 | | void call_heur_dissector_direct(heur_dtbl_entry_t *heur_dtbl_entry, tvbuff_t *tvb, |
3736 | | packet_info *pinfo, proto_tree *tree, void *data) |
3737 | 0 | { |
3738 | 0 | const char *saved_curr_proto; |
3739 | 0 | unsigned saved_proto_layer_num; |
3740 | 0 | const char *saved_heur_list_name; |
3741 | 0 | uint16_t saved_can_desegment; |
3742 | 0 | unsigned saved_layers_len = 0; |
3743 | |
|
3744 | 0 | DISSECTOR_ASSERT(heur_dtbl_entry); |
3745 | | |
3746 | | /* can_desegment is set to 2 by anyone which offers this api/service. |
3747 | | then every time a subdissector is called it is decremented by one. |
3748 | | thus only the subdissector immediately on top of whoever offers this |
3749 | | service can use it. |
3750 | | We save the current value of "can_desegment" for the |
3751 | | benefit of TCP proxying dissectors such as SOCKS, so they |
3752 | | can restore it and allow the dissectors they call to use |
3753 | | the desegmentation service. |
3754 | | */ |
3755 | 0 | saved_can_desegment = pinfo->can_desegment; |
3756 | 0 | pinfo->saved_can_desegment = saved_can_desegment; |
3757 | 0 | pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0); |
3758 | |
|
3759 | 0 | saved_curr_proto = pinfo->current_proto; |
3760 | 0 | saved_proto_layer_num = pinfo->curr_proto_layer_num; |
3761 | 0 | saved_heur_list_name = pinfo->heur_list_name; |
3762 | |
|
3763 | 0 | saved_layers_len = wmem_list_count(pinfo->layers); |
3764 | |
|
3765 | 0 | if (!heur_dtbl_entry->enabled || |
3766 | 0 | (heur_dtbl_entry->protocol != NULL && !proto_is_protocol_enabled(heur_dtbl_entry->protocol))) { |
3767 | 0 | DISSECTOR_ASSERT(data_handle->protocol != NULL); |
3768 | 0 | call_dissector_work(data_handle, tvb, pinfo, tree, true, NULL); |
3769 | 0 | return; |
3770 | 0 | } |
3771 | | |
3772 | 0 | if (heur_dtbl_entry->protocol != NULL) { |
3773 | | /* do NOT change this behavior - wslua uses the protocol short name set here in order |
3774 | | to determine which Lua-based heuristic dissector to call */ |
3775 | 0 | pinfo->current_proto = proto_get_protocol_short_name(heur_dtbl_entry->protocol); |
3776 | 0 | add_layer(pinfo, proto_get_id(heur_dtbl_entry->protocol)); |
3777 | 0 | } |
3778 | |
|
3779 | 0 | pinfo->heur_list_name = heur_dtbl_entry->list_name; |
3780 | | |
3781 | | /* call the dissector, in case of failure call data handle (might happen with exported PDUs) */ |
3782 | 0 | if (!(*heur_dtbl_entry->dissector)(tvb, pinfo, tree, data)) { |
3783 | | /* |
3784 | | * We added a protocol layer above. The dissector |
3785 | | * didn't accept the packet or it didn't add any |
3786 | | * items to the tree so remove it from the list. |
3787 | | */ |
3788 | 0 | while (wmem_list_count(pinfo->layers) > saved_layers_len) { |
3789 | 0 | remove_last_layer(pinfo, true); |
3790 | 0 | } |
3791 | |
|
3792 | 0 | call_dissector_work(data_handle, tvb, pinfo, tree, true, NULL); |
3793 | 0 | } |
3794 | | |
3795 | | /* XXX: Remove layers if it was accepted but didn't actually consume |
3796 | | * data due to desegmentation? (Currently the only callers of this |
3797 | | * are UDP and exported PDUs, so not yet necessary.) |
3798 | | */ |
3799 | | |
3800 | | /* Restore info from caller */ |
3801 | 0 | pinfo->can_desegment = saved_can_desegment; |
3802 | 0 | pinfo->current_proto = saved_curr_proto; |
3803 | 0 | pinfo->curr_proto_layer_num = saved_proto_layer_num; |
3804 | 0 | pinfo->heur_list_name = saved_heur_list_name; |
3805 | |
|
3806 | 0 | } |
3807 | | |
3808 | | bool register_depend_dissector(const char* parent, const char* dependent) |
3809 | 61.0k | { |
3810 | 61.0k | depend_dissector_list_t sub_dissectors; |
3811 | | |
3812 | 61.0k | if ((parent == NULL) || (dependent == NULL)) |
3813 | 16 | { |
3814 | | /* XXX - assert on parent? */ |
3815 | 16 | return false; |
3816 | 16 | } |
3817 | | |
3818 | 61.0k | sub_dissectors = find_depend_dissector_list(parent); |
3819 | 61.0k | if (sub_dissectors == NULL) { |
3820 | | /* parent protocol doesn't exist, create it */ |
3821 | 8.25k | sub_dissectors = g_slice_new(struct depend_dissector_list); |
3822 | 8.25k | sub_dissectors->dissectors = g_hash_table_new(g_str_hash, g_str_equal); /* initially empty */ |
3823 | 8.25k | g_hash_table_insert(depend_dissector_lists, (void *)g_strdup(parent), (void *) sub_dissectors); |
3824 | 8.25k | } |
3825 | | |
3826 | | /* Verify that sub-dissector is not already in the list */ |
3827 | 61.0k | g_hash_table_add(sub_dissectors->dissectors, (void *)dependent); |
3828 | 61.0k | return true; |
3829 | 61.0k | } |
3830 | | |
3831 | | bool deregister_depend_dissector(const char* parent, const char* dependent) |
3832 | 0 | { |
3833 | 0 | depend_dissector_list_t sub_dissectors = find_depend_dissector_list(parent); |
3834 | | |
3835 | | /* sanity check */ |
3836 | 0 | ws_assert(sub_dissectors != NULL); |
3837 | |
|
3838 | 0 | return remove_depend_dissector_from_list(sub_dissectors, dependent); |
3839 | 0 | } |
3840 | | |
3841 | | depend_dissector_list_t find_depend_dissector_list(const char* name) |
3842 | 61.0k | { |
3843 | 61.0k | return (depend_dissector_list_t)g_hash_table_lookup(depend_dissector_lists, name); |
3844 | 61.0k | } |
3845 | | |
3846 | | /* |
3847 | | * Dumps the "layer type"/"decode as" associations to stdout, similar |
3848 | | * to the proto_registrar_dump_*() routines. |
3849 | | * |
3850 | | * There is one record per line. The fields are tab-delimited. |
3851 | | * |
3852 | | * Field 1 = layer type, e.g. "tcp.port" |
3853 | | * Field 2 = selector - decimal for integer tables, strings for string tables, |
3854 | | * blank for payload tables. Custom and GUID tables aren't shown. |
3855 | | * Field 3 = "decode as" name, e.g. "http" |
3856 | | * |
3857 | | * XXX - View -> Internals -> Dissector Tables in the GUI includes the UI name, |
3858 | | * and separates tables by category. We could add fields for the the UI name |
3859 | | * and category. |
3860 | | * |
3861 | | * The GUI doesn't display FT_NONE (it should) nor FT_GUID tables, but does |
3862 | | * FT_BYTES (Custom) tables with the handle description name as key. |
3863 | | * That may or may not be helpful. |
3864 | | */ |
3865 | | |
3866 | | |
3867 | | static void |
3868 | | dissector_dump_decodes_display(const char *table_name, |
3869 | | ftenum_t selector_type _U_, void *key, void *value) |
3870 | 0 | { |
3871 | 0 | dissector_table_t sub_dissectors = find_dissector_table(table_name); |
3872 | 0 | dtbl_entry_t *dtbl_entry; |
3873 | 0 | dissector_handle_t handle; |
3874 | 0 | int proto_id; |
3875 | 0 | const char *decode_as; |
3876 | 0 | char fstring[32]; |
3877 | 0 | int field_width = 0; |
3878 | |
|
3879 | 0 | ws_assert(sub_dissectors); |
3880 | |
|
3881 | 0 | dtbl_entry = (dtbl_entry_t *)value; |
3882 | 0 | ws_assert(dtbl_entry); |
3883 | |
|
3884 | 0 | handle = dtbl_entry->current; |
3885 | | /* current might be NULL, if there was an initial value but then |
3886 | | * set to no handle via Decode As. */ |
3887 | 0 | if (!handle) |
3888 | 0 | return; |
3889 | | |
3890 | 0 | proto_id = dissector_handle_get_protocol_index(handle); |
3891 | |
|
3892 | 0 | if (proto_id != -1) { |
3893 | 0 | decode_as = proto_get_protocol_filter_name(proto_id); |
3894 | 0 | ws_assert(decode_as != NULL); |
3895 | 0 | switch (sub_dissectors->type) { |
3896 | 0 | case FT_UINT32: |
3897 | 0 | field_width += 2; |
3898 | | // fallthrough |
3899 | 0 | case FT_UINT24: |
3900 | 0 | field_width += 2; |
3901 | | // fallthrough |
3902 | 0 | case FT_UINT16: |
3903 | 0 | field_width += 2; |
3904 | | // fallthrough |
3905 | 0 | case FT_UINT8: |
3906 | 0 | field_width += 2; |
3907 | 0 | switch (sub_dissectors->param) |
3908 | 0 | { |
3909 | 0 | case BASE_OCT: |
3910 | 0 | snprintf(fstring, 32, "%%s\t0%%o\t%%s\n"); |
3911 | 0 | break; |
3912 | | |
3913 | 0 | case BASE_HEX: |
3914 | 0 | snprintf(fstring, 32, "%%s\t0x%%0%ux\t%%s\n", field_width); |
3915 | 0 | break; |
3916 | | |
3917 | 0 | case BASE_DEC: |
3918 | 0 | default: |
3919 | 0 | snprintf(fstring, 32, "%%s\t%%u\t%%s\n"); |
3920 | 0 | break; |
3921 | 0 | }; |
3922 | |
|
3923 | 0 | printf(fstring, table_name, GPOINTER_TO_UINT(key), decode_as); |
3924 | 0 | break; |
3925 | | |
3926 | 0 | case FT_STRING: |
3927 | 0 | printf("%s\t%s\t%s\n", table_name, (char*)key, decode_as); |
3928 | 0 | break; |
3929 | | |
3930 | 0 | case FT_NONE: |
3931 | 0 | printf("%s\t\t%s\n", table_name, decode_as); |
3932 | 0 | break; |
3933 | | |
3934 | 0 | case FT_GUID: |
3935 | | // We could output something here with the guid_key |
3936 | 0 | break; |
3937 | | |
3938 | 0 | case FT_BYTES: |
3939 | | // View->Internals->Dissector Tables uses the description, |
3940 | | // but that doesn't tell anything about how the table is |
3941 | | // configured. (This isn't a list of all possible handles.) |
3942 | | // Is it useful to output? |
3943 | 0 | break; |
3944 | | |
3945 | 0 | default: |
3946 | 0 | break; |
3947 | 0 | } |
3948 | 0 | } |
3949 | 0 | } |
3950 | | |
3951 | | static int compare_ints(const void *a, const void *b) |
3952 | 0 | { |
3953 | 0 | uint32_t inta, intb; |
3954 | |
|
3955 | 0 | inta = GPOINTER_TO_UINT(a); |
3956 | 0 | intb = GPOINTER_TO_UINT(b); |
3957 | |
|
3958 | 0 | if (inta < intb) |
3959 | 0 | return -1; |
3960 | 0 | if (inta > intb) |
3961 | 0 | return 1; |
3962 | 0 | return 0; |
3963 | 0 | } |
3964 | | |
3965 | | static void |
3966 | | dissector_dump_table_decodes(const char *table_name, const char *ui_name _U_, void *user_data _U_) |
3967 | 0 | { |
3968 | 0 | dissector_table_t sub_dissectors = find_dissector_table(table_name); |
3969 | 0 | GList *keys; |
3970 | |
|
3971 | 0 | ws_assert(sub_dissectors); |
3972 | 0 | keys = g_hash_table_get_keys(sub_dissectors->hash_table); |
3973 | |
|
3974 | 0 | switch (sub_dissectors->type) { |
3975 | 0 | case FT_UINT8: |
3976 | 0 | case FT_UINT16: |
3977 | 0 | case FT_UINT24: |
3978 | 0 | case FT_UINT32: |
3979 | 0 | keys = g_list_sort(keys, compare_ints); |
3980 | 0 | break; |
3981 | | |
3982 | 0 | case FT_STRING: |
3983 | 0 | case FT_STRINGZ: |
3984 | 0 | case FT_UINT_STRING: |
3985 | 0 | case FT_STRINGZPAD: |
3986 | 0 | case FT_STRINGZTRUNC: |
3987 | 0 | keys = g_list_sort(keys, (GCompareFunc)strcmp); |
3988 | 0 | break; |
3989 | | |
3990 | | /* FT_NONE we don't need to sort. We could do something for |
3991 | | * FT_GUID and FT_BYTES (Custom) if we were to output them, |
3992 | | * possibly with g_list_sort_with_data. |
3993 | | */ |
3994 | 0 | default: |
3995 | 0 | break; |
3996 | 0 | } |
3997 | | |
3998 | 0 | for (GList *entry = g_list_first(keys); entry; entry = entry->next) { |
3999 | 0 | void *key = entry->data; |
4000 | 0 | void *value = g_hash_table_lookup(sub_dissectors->hash_table, key); |
4001 | 0 | dissector_dump_decodes_display(table_name, sub_dissectors->type, key, value); |
4002 | 0 | } |
4003 | |
|
4004 | 0 | g_list_free(keys); |
4005 | 0 | } |
4006 | | |
4007 | | void |
4008 | | dissector_dump_decodes(void) |
4009 | 0 | { |
4010 | 0 | dissector_all_tables_foreach_table(dissector_dump_table_decodes, NULL, (GCompareFunc)strcmp); |
4011 | 0 | } |
4012 | | |
4013 | | /* |
4014 | | * Dumps information about dissector tables to stdout. |
4015 | | * |
4016 | | * There is one record per line. The fields are tab-delimited. |
4017 | | * |
4018 | | * Field 1 = dissector table name, e.g. "tcp.port" |
4019 | | * Field 2 = name used for the dissector table in the GUI |
4020 | | * Field 3 = type (textual representation of the ftenum type) |
4021 | | * Field 4 = base for display (for integer types) |
4022 | | * Field 5 = protocol name |
4023 | | * Field 6 = "decode as" support |
4024 | | * |
4025 | | * This does not dump the *individual entries* in the dissector tables, |
4026 | | * i.e. it doesn't show what dissector handles what particular value |
4027 | | * of the key in the dissector table. |
4028 | | */ |
4029 | | |
4030 | | static void |
4031 | | dissector_dump_dissector_tables_display (void *key, void *user_data _U_) |
4032 | 0 | { |
4033 | 0 | const char *table_name = (const char *)key; |
4034 | 0 | dissector_table_t table; |
4035 | |
|
4036 | 0 | table = (dissector_table_t)g_hash_table_lookup(dissector_tables, key); |
4037 | 0 | printf("%s\t%s\t%s", table_name, table->ui_name, ftype_name(table->type)); |
4038 | 0 | switch (table->type) { |
4039 | | |
4040 | 0 | case FT_UINT8: |
4041 | 0 | case FT_UINT16: |
4042 | 0 | case FT_UINT24: |
4043 | 0 | case FT_UINT32: |
4044 | 0 | switch(table->param) { |
4045 | | |
4046 | 0 | case BASE_NONE: |
4047 | 0 | printf("\tBASE_NONE"); |
4048 | 0 | break; |
4049 | | |
4050 | 0 | case BASE_DEC: |
4051 | 0 | printf("\tBASE_DEC"); |
4052 | 0 | break; |
4053 | | |
4054 | 0 | case BASE_HEX: |
4055 | 0 | printf("\tBASE_HEX"); |
4056 | 0 | break; |
4057 | | |
4058 | 0 | case BASE_OCT: |
4059 | 0 | printf("\tBASE_OCT"); |
4060 | 0 | break; |
4061 | | |
4062 | 0 | default: |
4063 | 0 | printf("\t%d", table->param); |
4064 | 0 | break; |
4065 | 0 | } |
4066 | 0 | break; |
4067 | | |
4068 | 0 | default: |
4069 | 0 | break; |
4070 | 0 | } |
4071 | 0 | if (table->protocol != NULL) { |
4072 | 0 | printf("\t%s", |
4073 | 0 | proto_get_protocol_short_name(table->protocol)); |
4074 | 0 | } else |
4075 | 0 | printf("\t(no protocol)"); |
4076 | 0 | printf("\tDecode As %ssupported", |
4077 | 0 | dissector_table_supports_decode_as(table) ? "" : "not "); |
4078 | 0 | printf("\n"); |
4079 | 0 | } |
4080 | | |
4081 | | /** The output format of this function is meant to parallel |
4082 | | * that of dissector_dump_dissector_tables_display(). |
4083 | | * Field 3 is shown as "heuristic". |
4084 | | * Field 4 is omitted, as it is for FT_STRING dissector tables above. |
4085 | | * Field 6 is omitted since "Decode As" doesn't apply. |
4086 | | */ |
4087 | | |
4088 | | static void |
4089 | | dissector_dump_heur_dissector_tables_display (void *key, void *user_data _U_) |
4090 | 0 | { |
4091 | 0 | const char *list_name = (const char *)key; |
4092 | 0 | heur_dissector_list_t list; |
4093 | |
|
4094 | 0 | list = (heur_dissector_list_t)g_hash_table_lookup(heur_dissector_lists, key); |
4095 | 0 | printf("%s\t%s\theuristic", list_name, list->ui_name ? list->ui_name : list_name); |
4096 | |
|
4097 | 0 | if (list->protocol != NULL) { |
4098 | 0 | printf("\t%s", |
4099 | 0 | proto_get_protocol_short_name(list->protocol)); |
4100 | 0 | } else |
4101 | 0 | printf("\t(no protocol)"); |
4102 | 0 | printf("\n"); |
4103 | 0 | } |
4104 | | |
4105 | | static int |
4106 | | compare_dissector_key_name(const void *dissector_a, const void *dissector_b) |
4107 | 0 | { |
4108 | 0 | return strcmp((const char*)dissector_a, (const char*)dissector_b); |
4109 | 0 | } |
4110 | | |
4111 | | void |
4112 | | dissector_dump_dissector_tables(void) |
4113 | 0 | { |
4114 | 0 | GList *list; |
4115 | |
|
4116 | 0 | list = g_hash_table_get_keys(dissector_tables); |
4117 | 0 | list = g_list_sort(list, compare_dissector_key_name); |
4118 | 0 | g_list_foreach(list, dissector_dump_dissector_tables_display, NULL); |
4119 | 0 | g_list_free(list); |
4120 | |
|
4121 | 0 | list = g_hash_table_get_keys(heur_dissector_lists); |
4122 | 0 | list = g_list_sort(list, compare_dissector_key_name); |
4123 | 0 | g_list_foreach(list, dissector_dump_heur_dissector_tables_display, NULL); |
4124 | 0 | g_list_free(list); |
4125 | 0 | } |
4126 | | |
4127 | | /* |
4128 | | * Dumps the entries in the table of registered dissectors. |
4129 | | * |
4130 | | * There is one record per line. The fields are tab-delimited. |
4131 | | * |
4132 | | * Field 1 = dissector name |
4133 | | * Field 2 = dissector description |
4134 | | */ |
4135 | | |
4136 | | struct dissector_info { |
4137 | | const char *name; |
4138 | | const char *description; |
4139 | | }; |
4140 | | |
4141 | | static int |
4142 | | compare_dissector_info_names(const void *arg1, const void *arg2) |
4143 | 0 | { |
4144 | 0 | const struct dissector_info *info1 = (const struct dissector_info *) arg1; |
4145 | 0 | const struct dissector_info *info2 = (const struct dissector_info *) arg2; |
4146 | |
|
4147 | 0 | return strcmp(info1->name, info2->name); |
4148 | 0 | } |
4149 | | |
4150 | | void |
4151 | | dissector_dump_dissectors(void) |
4152 | 0 | { |
4153 | 0 | GHashTableIter iter; |
4154 | 0 | struct dissector_info *dissectors_info; |
4155 | 0 | unsigned num_protocols; |
4156 | 0 | void *key, *value; |
4157 | 0 | unsigned proto_index; |
4158 | |
|
4159 | 0 | g_hash_table_iter_init(&iter, registered_dissectors); |
4160 | 0 | num_protocols = g_hash_table_size(registered_dissectors); |
4161 | 0 | dissectors_info = g_new(struct dissector_info, num_protocols); |
4162 | 0 | proto_index = 0; |
4163 | 0 | while (g_hash_table_iter_next(&iter, &key, &value)) { |
4164 | 0 | dissectors_info[proto_index].name = (const char *)key; |
4165 | 0 | dissectors_info[proto_index].description = |
4166 | 0 | ((dissector_handle_t) value)->description; |
4167 | 0 | proto_index++; |
4168 | 0 | } |
4169 | 0 | qsort(dissectors_info, num_protocols, sizeof(struct dissector_info), |
4170 | 0 | compare_dissector_info_names); |
4171 | 0 | for (proto_index = 0; proto_index < num_protocols; proto_index++) { |
4172 | 0 | printf("%s\t%s\n", dissectors_info[proto_index].name, |
4173 | 0 | dissectors_info[proto_index].description); |
4174 | 0 | } |
4175 | 0 | g_free(dissectors_info); |
4176 | 0 | } |
4177 | | |
4178 | | void |
4179 | | register_postdissector(dissector_handle_t handle) |
4180 | 64 | { |
4181 | 64 | postdissector p; |
4182 | | |
4183 | 64 | p.handle = handle; |
4184 | 64 | p.wanted_hfids = NULL; |
4185 | 64 | postdissectors = g_array_append_val(postdissectors, p); |
4186 | 64 | } |
4187 | | |
4188 | | void |
4189 | | set_postdissector_wanted_hfids(dissector_handle_t handle, GArray *wanted_hfids) |
4190 | 0 | { |
4191 | 0 | unsigned i; |
4192 | |
|
4193 | 0 | if (!postdissectors) return; |
4194 | | |
4195 | 0 | for (i = 0; i < postdissectors->len; i++) { |
4196 | 0 | if (POSTDISSECTORS(i).handle == handle) { |
4197 | 0 | if (POSTDISSECTORS(i).wanted_hfids) { |
4198 | 0 | g_array_free(POSTDISSECTORS(i).wanted_hfids, true); |
4199 | 0 | } |
4200 | 0 | POSTDISSECTORS(i).wanted_hfids = wanted_hfids; |
4201 | 0 | break; |
4202 | 0 | } |
4203 | 0 | } |
4204 | 0 | } |
4205 | | |
4206 | | void |
4207 | | deregister_postdissector(dissector_handle_t handle) |
4208 | 0 | { |
4209 | 0 | unsigned i; |
4210 | |
|
4211 | 0 | if (!postdissectors) return; |
4212 | | |
4213 | 0 | for (i = 0; i < postdissectors->len; i++) { |
4214 | 0 | if (POSTDISSECTORS(i).handle == handle) { |
4215 | 0 | if (POSTDISSECTORS(i).wanted_hfids) { |
4216 | 0 | g_array_free(POSTDISSECTORS(i).wanted_hfids, true); |
4217 | 0 | } |
4218 | 0 | postdissectors = g_array_remove_index_fast(postdissectors, i); |
4219 | 0 | break; |
4220 | 0 | } |
4221 | 0 | } |
4222 | 0 | } |
4223 | | |
4224 | | bool |
4225 | | have_postdissector(void) |
4226 | 191k | { |
4227 | 191k | unsigned i; |
4228 | 191k | dissector_handle_t handle; |
4229 | | |
4230 | 764k | for (i = 0; i < postdissectors->len; i++) { |
4231 | 764k | handle = POSTDISSECTORS(i).handle; |
4232 | | |
4233 | 764k | if (handle->protocol != NULL |
4234 | 764k | && proto_is_protocol_enabled(handle->protocol)) { |
4235 | | /* We have at least one enabled postdissector */ |
4236 | 191k | return true; |
4237 | 191k | } |
4238 | 764k | } |
4239 | 0 | return false; |
4240 | 191k | } |
4241 | | |
4242 | | void |
4243 | | call_all_postdissectors(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
4244 | 191k | { |
4245 | 191k | unsigned i; |
4246 | | |
4247 | 956k | for (i = 0; i < postdissectors->len; i++) { |
4248 | 764k | call_dissector_only(POSTDISSECTORS(i).handle, |
4249 | 764k | tvb, pinfo, tree, NULL); |
4250 | 764k | } |
4251 | 191k | } |
4252 | | |
4253 | | bool |
4254 | | postdissectors_want_hfids(void) |
4255 | 0 | { |
4256 | 0 | unsigned i; |
4257 | |
|
4258 | 0 | for (i = 0; i < postdissectors->len; i++) { |
4259 | 0 | if (POSTDISSECTORS(i).wanted_hfids != NULL && |
4260 | 0 | POSTDISSECTORS(i).wanted_hfids->len != 0 && |
4261 | 0 | (POSTDISSECTORS(i).handle->protocol == NULL || |
4262 | 0 | proto_is_protocol_enabled(POSTDISSECTORS(i).handle->protocol))) |
4263 | 0 | return true; |
4264 | 0 | } |
4265 | 0 | return false; |
4266 | 0 | } |
4267 | | |
4268 | | void |
4269 | | prime_epan_dissect_with_postdissector_wanted_hfids(epan_dissect_t *edt) |
4270 | 191k | { |
4271 | 191k | unsigned i; |
4272 | | |
4273 | 191k | if (postdissectors == NULL) { |
4274 | | /* |
4275 | | * No postdissector expressed an interest in any hfids. |
4276 | | */ |
4277 | 0 | return; |
4278 | 0 | } |
4279 | 956k | for (i = 0; i < postdissectors->len; i++) { |
4280 | 764k | if (POSTDISSECTORS(i).wanted_hfids != NULL && |
4281 | 0 | POSTDISSECTORS(i).wanted_hfids->len != 0 && |
4282 | 0 | (POSTDISSECTORS(i).handle->protocol == NULL || |
4283 | 0 | proto_is_protocol_enabled(POSTDISSECTORS(i).handle->protocol))) |
4284 | 0 | epan_dissect_prime_with_hfid_array(edt, |
4285 | 0 | POSTDISSECTORS(i).wanted_hfids); |
4286 | 764k | } |
4287 | 191k | } |
4288 | | |
4289 | | void |
4290 | 3.45M | increment_dissection_depth_by_n(packet_info *pinfo, unsigned n) { |
4291 | 3.45M | DISSECTOR_ASSERT_HINT(!ckd_add(&pinfo->dissection_depth, pinfo->dissection_depth, n), |
4292 | 3.45M | "pinfo->dissection_depth overflowed."); |
4293 | 3.45M | DISSECTOR_ASSERT(pinfo->dissection_depth < prefs.gui_max_tree_depth); |
4294 | 3.45M | } |
4295 | | |
4296 | | void |
4297 | 3.03M | increment_dissection_depth(packet_info *pinfo) { |
4298 | 3.03M | increment_dissection_depth_by_n(pinfo, 1); |
4299 | 3.03M | } |
4300 | | |
4301 | | void |
4302 | 3.26M | decrement_dissection_depth_by_n(packet_info *pinfo, unsigned n) { |
4303 | 3.26M | DISSECTOR_ASSERT_HINT(!ckd_sub(&pinfo->dissection_depth, pinfo->dissection_depth, n), |
4304 | 3.26M | "pinfo->dissection_depth underflowed."); |
4305 | 3.26M | } |
4306 | | |
4307 | | void |
4308 | 2.87M | decrement_dissection_depth(packet_info *pinfo) { |
4309 | 2.87M | decrement_dissection_depth_by_n(pinfo, 1); |
4310 | 2.87M | } |
4311 | | |
4312 | | /* |
4313 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
4314 | | * |
4315 | | * Local variables: |
4316 | | * c-basic-offset: 8 |
4317 | | * tab-width: 8 |
4318 | | * indent-tabs-mode: t |
4319 | | * End: |
4320 | | * |
4321 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
4322 | | * :indentSize=8:tabSize=8:noTabs=false: |
4323 | | */ |