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