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