/src/wireshark/epan/epan.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* epan.c |
2 | | * |
3 | | * Wireshark Protocol Analyzer Library |
4 | | * |
5 | | * Copyright (c) 2001 by Gerald Combs <gerald@wireshark.org> |
6 | | * |
7 | | * SPDX-License-Identifier: GPL-2.0-or-later |
8 | | */ |
9 | | |
10 | | #include "config.h" |
11 | | #include "epan.h" |
12 | | |
13 | | #include <stdarg.h> |
14 | | #include <stdio.h> |
15 | | #include <stdlib.h> |
16 | | |
17 | | #include <gcrypt.h> |
18 | | |
19 | | #ifdef HAVE_LIBGNUTLS |
20 | | #include <gnutls/gnutls.h> |
21 | | #endif /* HAVE_LIBGNUTLS */ |
22 | | |
23 | | #include <glib.h> |
24 | | |
25 | | #include <wsutil/report_message.h> |
26 | | |
27 | | #include <epan/exceptions.h> |
28 | | |
29 | | #include "epan/frame_data.h" |
30 | | |
31 | | #include "dfilter/dfilter.h" |
32 | | #include "dfilter/dfilter-translator.h" |
33 | | #include "epan_dissect.h" |
34 | | |
35 | | #include <wsutil/nstime.h> |
36 | | #include <wsutil/wslog.h> |
37 | | #include <wsutil/ws_assert.h> |
38 | | #include <wsutil/version_info.h> |
39 | | |
40 | | #include "conversation.h" |
41 | | #include "except.h" |
42 | | #include "packet.h" |
43 | | #include "prefs.h" |
44 | | #include "column-info.h" |
45 | | #include "tap.h" |
46 | | #include "addr_resolv.h" |
47 | | #include "oids.h" |
48 | | #include <epan/wmem_scopes.h> |
49 | | #include "expert.h" |
50 | | #include "print.h" |
51 | | #include "capture_dissectors.h" |
52 | | #include "exported_pdu.h" |
53 | | #include "export_object.h" |
54 | | #include "stat_tap_ui.h" |
55 | | #include "follow.h" |
56 | | #include "disabled_protos.h" |
57 | | #include "decode_as.h" |
58 | | #include "conversation_filter.h" |
59 | | #include "conversation_table.h" |
60 | | #include "reassemble.h" |
61 | | #include "srt_table.h" |
62 | | #include "stats_tree.h" |
63 | | #include "secrets.h" |
64 | | #include "funnel.h" |
65 | | #include "wscbor.h" |
66 | | #include <dtd.h> |
67 | | |
68 | | #ifdef HAVE_PLUGINS |
69 | | #include <wsutil/plugins.h> |
70 | | #endif |
71 | | |
72 | | #ifdef HAVE_LUA |
73 | | #include <lua.h> |
74 | | #include <wslua/wslua.h> |
75 | | #endif |
76 | | |
77 | | #ifdef HAVE_LIBSMI |
78 | | #include <smi.h> |
79 | | #endif |
80 | | |
81 | | #include <ares.h> |
82 | | |
83 | | #ifdef HAVE_LZ4 |
84 | | #include <lz4.h> |
85 | | #endif |
86 | | |
87 | | #ifdef HAVE_ZSTD |
88 | | #include <zstd.h> |
89 | | #endif |
90 | | |
91 | | #ifdef HAVE_NGHTTP2 |
92 | | #include <nghttp2/nghttp2.h> |
93 | | #endif |
94 | | |
95 | | #ifdef HAVE_NGHTTP3 |
96 | | #include <nghttp3/nghttp3.h> |
97 | | #endif |
98 | | |
99 | | #ifdef HAVE_BROTLI |
100 | | #include <brotli/decode.h> |
101 | | #endif |
102 | | |
103 | | #ifdef HAVE_LIBXML2 |
104 | | #include <libxml/xmlversion.h> |
105 | | #include <libxml/parser.h> |
106 | | #endif |
107 | | |
108 | | #ifndef _WIN32 |
109 | | #include <signal.h> |
110 | | #endif |
111 | | |
112 | | static GSList *epan_plugin_register_all_procotols; |
113 | | static GSList *epan_plugin_register_all_handoffs; |
114 | | |
115 | | static wmem_allocator_t *pinfo_pool_cache; |
116 | | |
117 | | /* Global variables holding the content of the corresponding environment variable |
118 | | * to save fetching it repeatedly. |
119 | | */ |
120 | | bool wireshark_abort_on_dissector_bug; |
121 | | bool wireshark_abort_on_too_many_items; |
122 | | |
123 | | void |
124 | | ws_dissector_bug(const char *format, ...) |
125 | 0 | { |
126 | 0 | va_list ap; |
127 | |
|
128 | 0 | va_start(ap, format); |
129 | 0 | vfprintf(stderr, format, ap); |
130 | 0 | va_end(ap); |
131 | |
|
132 | 0 | if (wireshark_abort_on_dissector_bug) |
133 | 0 | abort(); |
134 | 0 | } |
135 | | |
136 | | #ifdef HAVE_PLUGINS |
137 | | /* Used for bookkeeping, includes all libwireshark plugin types (dissector, tap, epan). */ |
138 | | static plugins_t *libwireshark_plugins; |
139 | | #endif |
140 | | |
141 | | /* "epan_plugins" are a specific type of libwireshark plugin (the name isn't the best for clarity). */ |
142 | | static GSList *epan_plugins; |
143 | | |
144 | | const char* |
145 | 0 | epan_get_version(void) { |
146 | 0 | return VERSION; |
147 | 0 | } |
148 | | |
149 | | void |
150 | | epan_get_version_number(int *major, int *minor, int *micro) |
151 | 0 | { |
152 | 0 | if (major) |
153 | 0 | *major = VERSION_MAJOR; |
154 | 0 | if (minor) |
155 | 0 | *minor = VERSION_MINOR; |
156 | 0 | if (micro) |
157 | 0 | *micro = VERSION_MICRO; |
158 | 0 | } |
159 | | |
160 | | #if defined(_WIN32) && GCRYPT_VERSION_NUMBER < 0x010b00 |
161 | | // Libgcrypt prints all log messages to stderr by default. This is noisier |
162 | | // than we would like on Windows. In particular slow_gatherer tends to print |
163 | | // "NOTE: you should run 'diskperf -y' to enable the disk statistics" |
164 | | // which we don't care about. |
165 | | // gcry_set_log_handler was deprecated in libgcrypt 1.11.0, and also that |
166 | | // particular log message was quieted when not supported (and hence not useful) |
167 | | // https://github.com/gpg/libgcrypt/commit/35abf4d2eb582b78873aa324f6d02976788ffbbc |
168 | | static void |
169 | | quiet_gcrypt_logger (void *dummy _U_, int level, const char *format, va_list args) |
170 | | { |
171 | | enum ws_log_level log_level; |
172 | | |
173 | | switch (level) { |
174 | | case GCRY_LOG_CONT: // Continuation. Ignore for now. |
175 | | case GCRY_LOG_DEBUG: |
176 | | case GCRY_LOG_INFO: |
177 | | return; |
178 | | case GCRY_LOG_WARN: |
179 | | case GCRY_LOG_BUG: |
180 | | log_level = LOG_LEVEL_WARNING; |
181 | | break; |
182 | | case GCRY_LOG_ERROR: |
183 | | log_level = LOG_LEVEL_ERROR; |
184 | | break; |
185 | | case GCRY_LOG_FATAL: |
186 | | log_level = LOG_LEVEL_CRITICAL; |
187 | | break; |
188 | | default: |
189 | | return; |
190 | | } |
191 | | ws_logv(LOG_DOMAIN_EPAN, log_level, format, args); |
192 | | } |
193 | | #endif // _WIN32 |
194 | | |
195 | | static void |
196 | | epan_plugin_init(void *data, void *user_data _U_) |
197 | 0 | { |
198 | 0 | ((epan_plugin *)data)->init(); |
199 | 0 | } |
200 | | |
201 | | static void |
202 | | epan_plugin_post_init(void *data, void *user_data _U_) |
203 | 0 | { |
204 | 0 | ((epan_plugin *)data)->post_init(); |
205 | 0 | } |
206 | | |
207 | | static void |
208 | | epan_plugin_dissect_init(void *data, void *user_data) |
209 | 0 | { |
210 | 0 | ((epan_plugin *)data)->dissect_init((epan_dissect_t *)user_data); |
211 | 0 | } |
212 | | |
213 | | static void |
214 | | epan_plugin_dissect_cleanup(void *data, void *user_data) |
215 | 0 | { |
216 | 0 | ((epan_plugin *)data)->dissect_cleanup((epan_dissect_t *)user_data); |
217 | 0 | } |
218 | | |
219 | | static void |
220 | | epan_plugin_cleanup(void *data, void *user_data _U_) |
221 | 0 | { |
222 | 0 | ((epan_plugin *)data)->cleanup(); |
223 | 0 | } |
224 | | |
225 | | #ifdef HAVE_PLUGINS |
226 | | void epan_register_plugin(const epan_plugin *plug) |
227 | | { |
228 | | epan_plugins = g_slist_prepend(epan_plugins, (epan_plugin *)plug); |
229 | | if (plug->register_all_protocols) |
230 | | epan_plugin_register_all_procotols = g_slist_prepend(epan_plugin_register_all_procotols, plug->register_all_protocols); |
231 | | if (plug->register_all_handoffs) |
232 | | epan_plugin_register_all_handoffs = g_slist_prepend(epan_plugin_register_all_handoffs, plug->register_all_handoffs); |
233 | | } |
234 | | #else /* HAVE_PLUGINS */ |
235 | | void epan_register_plugin(const epan_plugin *plug _U_) |
236 | 0 | { |
237 | 0 | ws_warning("epan_register_plugin: built without support for binary plugins"); |
238 | 0 | } |
239 | | #endif /* HAVE_PLUGINS */ |
240 | | |
241 | | int epan_plugins_supported(void) |
242 | 0 | { |
243 | | #ifdef HAVE_PLUGINS |
244 | | return plugins_supported() ? 0 : 1; |
245 | | #else |
246 | 0 | return -1; |
247 | 0 | #endif |
248 | 0 | } |
249 | | |
250 | | static void epan_plugin_register_all_tap_listeners(void *data, void *user_data _U_) |
251 | 0 | { |
252 | 0 | epan_plugin *plug = (epan_plugin *)data; |
253 | 0 | if (plug->register_all_tap_listeners) |
254 | 0 | plug->register_all_tap_listeners(); |
255 | 0 | } |
256 | | |
257 | | bool |
258 | | epan_init(register_cb cb, void *client_data, bool load_plugins) |
259 | 14 | { |
260 | 14 | volatile bool status = true; |
261 | | |
262 | | /* Get the value of some environment variables and set corresponding globals for performance reasons*/ |
263 | | /* If the WIRESHARK_ABORT_ON_DISSECTOR_BUG environment variable is set, |
264 | | * it will call abort(), instead, to make it easier to get a stack trace. |
265 | | */ |
266 | 14 | if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL) { |
267 | 0 | wireshark_abort_on_dissector_bug = true; |
268 | 14 | } else { |
269 | 14 | wireshark_abort_on_dissector_bug = false; |
270 | 14 | } |
271 | | |
272 | 14 | if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) { |
273 | 0 | wireshark_abort_on_too_many_items = true; |
274 | 14 | } else { |
275 | 14 | wireshark_abort_on_too_many_items = false; |
276 | 14 | } |
277 | | |
278 | | /* |
279 | | * proto_init -> register_all_protocols -> g_async_queue_new which |
280 | | * requires threads to be initialized. This happens automatically with |
281 | | * GLib 2.32, before that g_thread_init must be called. But only since |
282 | | * GLib 2.24, multiple invocations are allowed. Check for an earlier |
283 | | * invocation just in case. |
284 | | */ |
285 | | /* initialize memory allocation subsystem */ |
286 | 14 | wmem_init_scopes(); |
287 | | |
288 | | /* initialize the GUID to name mapping table */ |
289 | 14 | guids_init(); |
290 | | |
291 | | /* initialize name resolution (addr_resolv.c) */ |
292 | 14 | addr_resolv_init(); |
293 | | |
294 | 14 | except_init(); |
295 | | |
296 | 14 | dfilter_translator_init(); |
297 | | |
298 | 14 | if (load_plugins) { |
299 | | #ifdef HAVE_PLUGINS |
300 | | libwireshark_plugins = plugins_init(WS_PLUGIN_EPAN); |
301 | | #endif |
302 | 0 | } |
303 | | |
304 | | /* initialize libgcrypt (beware, it won't be thread-safe) */ |
305 | | #if GCRYPT_VERSION_NUMBER >= 0x010a00 |
306 | | /* Ensure FIPS mode is disabled; it makes it impossible to decrypt |
307 | | * non-NIST approved algorithms. We're decrypting, not promising |
308 | | * security. This overrides any file or environment variables that |
309 | | * would normally turn on FIPS mode, and has to be done prior to |
310 | | * gcry_check_version(). |
311 | | */ |
312 | | gcry_control (GCRYCTL_NO_FIPS_MODE); |
313 | | #endif |
314 | 14 | gcry_check_version(NULL); |
315 | | #if defined(_WIN32) && GCRYPT_VERSION_NUMBER < 0x010b00 |
316 | | gcry_set_log_handler (quiet_gcrypt_logger, NULL); |
317 | | #endif |
318 | 14 | gcry_control (GCRYCTL_DISABLE_SECMEM, 0); |
319 | 14 | gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); |
320 | | #ifdef HAVE_LIBGNUTLS |
321 | | gnutls_global_init(); |
322 | | #if GNUTLS_VERSION_NUMBER >= 0x030602 |
323 | | if (gnutls_fips140_mode_enabled()) { |
324 | | gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, 0); |
325 | | } |
326 | | #endif |
327 | | #endif |
328 | | #ifdef HAVE_LIBXML2 |
329 | | xmlInitParser(); |
330 | | LIBXML_TEST_VERSION; |
331 | | #endif |
332 | | |
333 | 14 | #ifndef _WIN32 |
334 | | // We might receive a SIGPIPE due to maxmind_db. |
335 | 14 | signal(SIGPIPE, SIG_IGN); |
336 | 14 | #endif |
337 | | |
338 | 14 | TRY { |
339 | 14 | export_pdu_init(); |
340 | 14 | tap_init(); |
341 | 14 | prefs_init(); |
342 | 14 | expert_init(); |
343 | 14 | packet_init(); |
344 | 14 | secrets_init(); |
345 | 14 | conversation_init(); |
346 | 14 | capture_dissector_init(); |
347 | 14 | reassembly_tables_init(); |
348 | 14 | conversation_filters_init(); |
349 | 14 | g_slist_foreach(epan_plugins, epan_plugin_init, NULL); |
350 | 14 | proto_init(epan_plugin_register_all_procotols, epan_plugin_register_all_handoffs, cb, client_data); |
351 | 14 | g_slist_foreach(epan_plugins, epan_plugin_register_all_tap_listeners, NULL); |
352 | 14 | packet_cache_proto_handles(); |
353 | 14 | dfilter_init(); |
354 | 14 | wscbor_init(); |
355 | 14 | final_registration_all_protocols(); |
356 | 14 | print_cache_field_handles(); |
357 | 14 | expert_packet_init(); |
358 | | #ifdef HAVE_LUA |
359 | | wslua_init(cb, client_data); |
360 | | #endif |
361 | 14 | g_slist_foreach(epan_plugins, epan_plugin_post_init, NULL); |
362 | 14 | } |
363 | 14 | CATCH(DissectorError) { |
364 | | /* |
365 | | * This is probably a dissector, or something it calls, |
366 | | * calling REPORT_DISSECTOR_ERROR() in a registration |
367 | | * routine or something else outside the normal dissection |
368 | | * code path. |
369 | | */ |
370 | 0 | const char *exception_message = GET_MESSAGE; |
371 | 0 | static const char dissector_error_nomsg[] = |
372 | 0 | "Dissector writer didn't bother saying what the error was"; |
373 | |
|
374 | 0 | report_failure("Dissector bug: %s", |
375 | 0 | exception_message == NULL ? |
376 | 0 | dissector_error_nomsg : exception_message); |
377 | 0 | if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL) |
378 | 0 | abort(); |
379 | 0 | status = false; |
380 | 0 | } |
381 | 14 | ENDTRY; |
382 | 14 | return status; |
383 | 14 | } |
384 | | |
385 | | /* |
386 | | * Load all settings, from the current profile, that affect libwireshark. |
387 | | */ |
388 | | e_prefs * |
389 | | epan_load_settings(void) |
390 | 14 | { |
391 | 14 | e_prefs *prefs_p; |
392 | | |
393 | | /* load the decode as entries of the current profile */ |
394 | 14 | load_decode_as_entries(); |
395 | | |
396 | 14 | prefs_p = read_prefs(); |
397 | | |
398 | | /* |
399 | | * Read the files that enable and disable protocols and heuristic |
400 | | * dissectors. |
401 | | */ |
402 | 14 | read_enabled_and_disabled_lists(); |
403 | | |
404 | 14 | return prefs_p; |
405 | 14 | } |
406 | | |
407 | | void |
408 | | epan_cleanup(void) |
409 | 0 | { |
410 | 0 | g_slist_foreach(epan_plugins, epan_plugin_cleanup, NULL); |
411 | 0 | g_slist_free(epan_plugins); |
412 | 0 | epan_plugins = NULL; |
413 | 0 | g_slist_free(epan_plugin_register_all_procotols); |
414 | 0 | epan_plugin_register_all_procotols = NULL; |
415 | 0 | g_slist_free(epan_plugin_register_all_handoffs); |
416 | 0 | epan_plugin_register_all_handoffs = NULL; |
417 | |
|
418 | 0 | dfilter_cleanup(); |
419 | 0 | decode_clear_all(); |
420 | 0 | decode_cleanup(); |
421 | |
|
422 | | #ifdef HAVE_LUA |
423 | | /* |
424 | | * Must deregister Proto objects in Lua before destroying dissector |
425 | | * tables in packet_cleanup(). Doing so will also deregister and free |
426 | | * preferences, this must happen before prefs_cleanup(). That will |
427 | | * update the list of deregistered fields which must be followed by |
428 | | * proto_cleanup() to complete deallocation. |
429 | | */ |
430 | | wslua_early_cleanup(); |
431 | | #endif |
432 | | |
433 | | /* |
434 | | * Note: packet_cleanup() will call registered shutdown routines which |
435 | | * may be used to deregister dynamically registered protocol fields, |
436 | | * and prefs_cleanup() will call uat_clear() which also may be used to |
437 | | * deregister dynamically registered protocol fields. This must be done |
438 | | * before proto_cleanup() to avoid inconsistency and memory leaks. |
439 | | */ |
440 | 0 | packet_cleanup(); |
441 | 0 | prefs_cleanup(); |
442 | 0 | proto_cleanup(); |
443 | |
|
444 | 0 | secrets_cleanup(); |
445 | 0 | conversation_filters_cleanup(); |
446 | 0 | reassembly_table_cleanup(); |
447 | 0 | tap_cleanup(); |
448 | 0 | expert_cleanup(); |
449 | 0 | capture_dissector_cleanup(); |
450 | 0 | export_pdu_cleanup(); |
451 | 0 | cleanup_enabled_and_disabled_lists(); |
452 | 0 | stats_tree_cleanup(); |
453 | 0 | funnel_cleanup(); |
454 | 0 | dtd_location(NULL); |
455 | | #ifdef HAVE_LUA |
456 | | wslua_cleanup(); |
457 | | #endif |
458 | | #ifdef HAVE_LIBGNUTLS |
459 | | gnutls_global_deinit(); |
460 | | #endif |
461 | | #ifdef HAVE_LIBXML2 |
462 | | xmlCleanupParser(); |
463 | | #endif |
464 | 0 | except_deinit(); |
465 | 0 | addr_resolv_cleanup(); |
466 | |
|
467 | 0 | dfilter_translator_cleanup(); |
468 | |
|
469 | 0 | if (pinfo_pool_cache != NULL) { |
470 | 0 | wmem_destroy_allocator(pinfo_pool_cache); |
471 | 0 | pinfo_pool_cache = NULL; |
472 | 0 | } |
473 | |
|
474 | 0 | wmem_cleanup_scopes(); |
475 | |
|
476 | | #ifdef HAVE_PLUGINS |
477 | | plugins_cleanup(libwireshark_plugins); |
478 | | libwireshark_plugins = NULL; |
479 | | #endif |
480 | 0 | } |
481 | | |
482 | | struct epan_session { |
483 | | struct packet_provider_data *prov; /* packet provider data for this session */ |
484 | | struct packet_provider_funcs funcs; /* functions using that data */ |
485 | | }; |
486 | | |
487 | | epan_t * |
488 | | epan_new(struct packet_provider_data *prov, |
489 | | const struct packet_provider_funcs *funcs) |
490 | 14 | { |
491 | 14 | epan_t *session = g_slice_new0(epan_t); |
492 | | |
493 | 14 | session->prov = prov; |
494 | 14 | session->funcs = *funcs; |
495 | | |
496 | | /* XXX, it should take session as param */ |
497 | 14 | init_dissection(); |
498 | | |
499 | 14 | return session; |
500 | 14 | } |
501 | | |
502 | | wtap_block_t |
503 | | epan_get_modified_block(const epan_t *session, const frame_data *fd) |
504 | 0 | { |
505 | 0 | if (session->funcs.get_modified_block) |
506 | 0 | return session->funcs.get_modified_block(session->prov, fd); |
507 | | |
508 | 0 | return NULL; |
509 | 0 | } |
510 | | |
511 | | const char * |
512 | | epan_get_interface_name(const epan_t *session, uint32_t interface_id, unsigned section_number) |
513 | 0 | { |
514 | 0 | if (session->funcs.get_interface_name) |
515 | 0 | return session->funcs.get_interface_name(session->prov, interface_id, section_number); |
516 | | |
517 | 0 | return NULL; |
518 | 0 | } |
519 | | |
520 | | const char * |
521 | | epan_get_interface_description(const epan_t *session, uint32_t interface_id, unsigned section_number) |
522 | 0 | { |
523 | 0 | if (session->funcs.get_interface_description) |
524 | 0 | return session->funcs.get_interface_description(session->prov, interface_id, section_number); |
525 | | |
526 | 0 | return NULL; |
527 | 0 | } |
528 | | |
529 | | const nstime_t * |
530 | | epan_get_frame_ts(const epan_t *session, uint32_t frame_num) |
531 | 167k | { |
532 | 167k | const nstime_t *abs_ts = NULL; |
533 | | |
534 | 167k | if (session && session->funcs.get_frame_ts) |
535 | 167k | abs_ts = session->funcs.get_frame_ts(session->prov, frame_num); |
536 | | |
537 | 167k | if (!abs_ts) { |
538 | | /* This can happen if frame_num doesn't have a ts */ |
539 | 0 | ws_debug("!!! couldn't get frame ts for %u !!!\n", frame_num); |
540 | 0 | } |
541 | | |
542 | 167k | return abs_ts; |
543 | 167k | } |
544 | | |
545 | | void |
546 | | epan_free(epan_t *session) |
547 | 0 | { |
548 | 0 | if (session) { |
549 | | /* XXX, it should take session as param */ |
550 | 0 | cleanup_dissection(); |
551 | |
|
552 | 0 | g_slice_free(epan_t, session); |
553 | 0 | } |
554 | 0 | } |
555 | | |
556 | | void |
557 | | epan_conversation_init(void) |
558 | 14 | { |
559 | 14 | conversation_epan_reset(); |
560 | 14 | } |
561 | | |
562 | | /* Overrides proto_tree_visible i epan_dissect_init to make all fields visible. |
563 | | * This is > 0 if a Lua script wanted to see all fields all the time. |
564 | | * This is ref-counted, so clearing it won't override other taps/scripts wanting it. |
565 | | */ |
566 | | static int always_visible_refcount; |
567 | | |
568 | | void |
569 | | epan_set_always_visible(bool force) |
570 | 0 | { |
571 | 0 | if (force) |
572 | 0 | always_visible_refcount++; |
573 | 0 | else if (always_visible_refcount > 0) |
574 | 0 | always_visible_refcount--; |
575 | 0 | } |
576 | | |
577 | | void |
578 | | epan_dissect_init(epan_dissect_t *edt, epan_t *session, const bool create_proto_tree, const bool proto_tree_visible) |
579 | 14 | { |
580 | 14 | ws_assert(edt); |
581 | | |
582 | 14 | edt->session = session; |
583 | | |
584 | 14 | memset(&edt->pi, 0, sizeof(edt->pi)); |
585 | 14 | if (pinfo_pool_cache != NULL) { |
586 | 0 | edt->pi.pool = pinfo_pool_cache; |
587 | 0 | pinfo_pool_cache = NULL; |
588 | 0 | } |
589 | 14 | else { |
590 | 14 | edt->pi.pool = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK_FAST); |
591 | 14 | } |
592 | | |
593 | 14 | if (create_proto_tree) { |
594 | 14 | edt->tree = proto_tree_create_root(&edt->pi); |
595 | 14 | proto_tree_set_visible(edt->tree, (always_visible_refcount > 0) ? true : proto_tree_visible); |
596 | 14 | } |
597 | 0 | else { |
598 | 0 | edt->tree = NULL; |
599 | 0 | } |
600 | | |
601 | 14 | edt->tvb = NULL; |
602 | | |
603 | 14 | g_slist_foreach(epan_plugins, epan_plugin_dissect_init, edt); |
604 | 14 | } |
605 | | |
606 | | void |
607 | | epan_dissect_reset(epan_dissect_t *edt) |
608 | 103k | { |
609 | | /* We have to preserve the pool pointer across the memzeroing */ |
610 | 103k | wmem_allocator_t *tmp; |
611 | | |
612 | 103k | ws_assert(edt); |
613 | | |
614 | 103k | wtap_block_unref(edt->pi.rec->block); |
615 | | |
616 | 103k | g_slist_free(edt->pi.proto_data); |
617 | | |
618 | | /* Free the data sources list. */ |
619 | 103k | free_data_sources(&edt->pi); |
620 | | |
621 | 103k | if (edt->tvb) { |
622 | | /* Free all tvb's chained from this tvb */ |
623 | 103k | tvb_free_chain(edt->tvb); |
624 | 103k | edt->tvb = NULL; |
625 | 103k | } |
626 | | |
627 | 103k | if (edt->tree) |
628 | 103k | proto_tree_reset(edt->tree); |
629 | | |
630 | 103k | tmp = edt->pi.pool; |
631 | 103k | wmem_free_all(tmp); |
632 | | |
633 | 103k | memset(&edt->pi, 0, sizeof(edt->pi)); |
634 | 103k | edt->pi.pool = tmp; |
635 | 103k | } |
636 | | |
637 | | epan_dissect_t* |
638 | | epan_dissect_new(epan_t *session, const bool create_proto_tree, const bool proto_tree_visible) |
639 | 14 | { |
640 | 14 | epan_dissect_t *edt; |
641 | | |
642 | 14 | edt = g_new0(epan_dissect_t, 1); |
643 | | |
644 | 14 | epan_dissect_init(edt, session, create_proto_tree, proto_tree_visible); |
645 | 14 | return edt; |
646 | 14 | } |
647 | | |
648 | | void |
649 | | epan_dissect_fake_protocols(epan_dissect_t *edt, const bool fake_protocols) |
650 | 0 | { |
651 | 0 | if (edt) |
652 | 0 | proto_tree_set_fake_protocols(edt->tree, fake_protocols); |
653 | 0 | } |
654 | | |
655 | | void |
656 | | epan_dissect_run(epan_dissect_t *edt, int file_type_subtype, |
657 | | wtap_rec *rec, frame_data *fd, column_info *cinfo) |
658 | 103k | { |
659 | | #ifdef HAVE_LUA |
660 | | wslua_prime_dfilter(edt); /* done before entering wmem scope */ |
661 | | #endif |
662 | 103k | wmem_enter_packet_scope(); |
663 | 103k | dissect_record(edt, file_type_subtype, rec, fd, cinfo); |
664 | | |
665 | | /* free all memory allocated */ |
666 | 103k | wmem_leave_packet_scope(); |
667 | 103k | wtap_block_unref(rec->block); |
668 | 103k | rec->block = NULL; |
669 | 103k | } |
670 | | |
671 | | void |
672 | | epan_dissect_run_with_taps(epan_dissect_t *edt, int file_type_subtype, |
673 | | wtap_rec *rec, frame_data *fd, column_info *cinfo) |
674 | 0 | { |
675 | 0 | wmem_enter_packet_scope(); |
676 | 0 | tap_queue_init(edt); |
677 | 0 | dissect_record(edt, file_type_subtype, rec, fd, cinfo); |
678 | 0 | tap_push_tapped_queue(edt); |
679 | | |
680 | | /* free all memory allocated */ |
681 | 0 | wmem_leave_packet_scope(); |
682 | 0 | wtap_block_unref(rec->block); |
683 | 0 | rec->block = NULL; |
684 | 0 | } |
685 | | |
686 | | void |
687 | | epan_dissect_file_run(epan_dissect_t *edt, wtap_rec *rec, |
688 | | frame_data *fd, column_info *cinfo) |
689 | 0 | { |
690 | | #ifdef HAVE_LUA |
691 | | wslua_prime_dfilter(edt); /* done before entering wmem scope */ |
692 | | #endif |
693 | 0 | wmem_enter_packet_scope(); |
694 | 0 | dissect_file(edt, rec, fd, cinfo); |
695 | | |
696 | | /* free all memory allocated */ |
697 | 0 | wmem_leave_packet_scope(); |
698 | 0 | wtap_block_unref(rec->block); |
699 | 0 | rec->block = NULL; |
700 | 0 | } |
701 | | |
702 | | void |
703 | | epan_dissect_file_run_with_taps(epan_dissect_t *edt, wtap_rec *rec, |
704 | | frame_data *fd, column_info *cinfo) |
705 | 0 | { |
706 | 0 | wmem_enter_packet_scope(); |
707 | 0 | tap_queue_init(edt); |
708 | 0 | dissect_file(edt, rec, fd, cinfo); |
709 | 0 | tap_push_tapped_queue(edt); |
710 | | |
711 | | /* free all memory allocated */ |
712 | 0 | wmem_leave_packet_scope(); |
713 | 0 | wtap_block_unref(rec->block); |
714 | 0 | rec->block = NULL; |
715 | 0 | } |
716 | | |
717 | | void |
718 | | epan_dissect_cleanup(epan_dissect_t* edt) |
719 | 0 | { |
720 | 0 | ws_assert(edt); |
721 | |
|
722 | 0 | g_slist_foreach(epan_plugins, epan_plugin_dissect_cleanup, edt); |
723 | |
|
724 | 0 | g_slist_free(edt->pi.proto_data); |
725 | | |
726 | | /* Free the data sources list. */ |
727 | 0 | free_data_sources(&edt->pi); |
728 | |
|
729 | 0 | if (edt->tvb) { |
730 | | /* Free all tvb's chained from this tvb */ |
731 | 0 | tvb_free_chain(edt->tvb); |
732 | 0 | } |
733 | |
|
734 | 0 | if (edt->tree) { |
735 | 0 | proto_tree_free(edt->tree); |
736 | 0 | } |
737 | |
|
738 | 0 | if (pinfo_pool_cache == NULL) { |
739 | 0 | wmem_free_all(edt->pi.pool); |
740 | 0 | pinfo_pool_cache = edt->pi.pool; |
741 | 0 | } |
742 | 0 | else { |
743 | 0 | wmem_destroy_allocator(edt->pi.pool); |
744 | 0 | } |
745 | 0 | } |
746 | | |
747 | | void |
748 | | epan_dissect_free(epan_dissect_t* edt) |
749 | 0 | { |
750 | 0 | epan_dissect_cleanup(edt); |
751 | 0 | g_free(edt); |
752 | 0 | } |
753 | | |
754 | | void |
755 | | epan_dissect_prime_with_dfilter(epan_dissect_t *edt, const dfilter_t* dfcode) |
756 | 0 | { |
757 | 0 | dfilter_prime_proto_tree(dfcode, edt->tree); |
758 | 0 | } |
759 | | |
760 | | void |
761 | | epan_dissect_prime_with_dfilter_print(epan_dissect_t *edt, const dfilter_t* dfcode) |
762 | 0 | { |
763 | 0 | dfilter_prime_proto_tree_print(dfcode, edt->tree); |
764 | 0 | } |
765 | | |
766 | | void |
767 | | epan_dissect_prime_with_hfid(epan_dissect_t *edt, int hfid) |
768 | 0 | { |
769 | 0 | proto_tree_prime_with_hfid(edt->tree, hfid); |
770 | 0 | } |
771 | | |
772 | | void |
773 | | epan_dissect_prime_with_hfid_array(epan_dissect_t *edt, GArray *hfids) |
774 | 0 | { |
775 | 0 | unsigned i; |
776 | |
|
777 | 0 | for (i = 0; i < hfids->len; i++) { |
778 | 0 | proto_tree_prime_with_hfid(edt->tree, |
779 | 0 | g_array_index(hfids, int, i)); |
780 | 0 | } |
781 | 0 | } |
782 | | |
783 | | /* ----------------------- */ |
784 | | const char * |
785 | | epan_custom_set(epan_dissect_t *edt, GSList *field_ids, |
786 | | int occurrence, |
787 | | bool display_details, |
788 | | char *result, |
789 | | char *expr, const int size ) |
790 | 0 | { |
791 | 0 | return proto_custom_set(edt->tree, field_ids, occurrence, display_details, result, expr, size); |
792 | 0 | } |
793 | | |
794 | | void |
795 | | epan_dissect_fill_in_columns(epan_dissect_t *edt, const bool fill_col_exprs, const bool fill_fd_colums) |
796 | 0 | { |
797 | 0 | col_custom_set_edt(edt, edt->pi.cinfo); |
798 | 0 | col_fill_in(&edt->pi, fill_col_exprs, fill_fd_colums); |
799 | 0 | } |
800 | | |
801 | | bool |
802 | | epan_dissect_packet_contains_field(epan_dissect_t* edt, |
803 | | const char *field_name) |
804 | 0 | { |
805 | 0 | GPtrArray* array; |
806 | 0 | int field_id; |
807 | 0 | bool contains_field; |
808 | |
|
809 | 0 | if (!edt || !edt->tree) |
810 | 0 | return false; |
811 | 0 | field_id = proto_get_id_by_filter_name(field_name); |
812 | 0 | if (field_id < 0) |
813 | 0 | return false; |
814 | 0 | array = proto_find_finfo(edt->tree, field_id); |
815 | 0 | contains_field = (array->len > 0) ? true : false; |
816 | 0 | g_ptr_array_free(array, true); |
817 | 0 | return contains_field; |
818 | 0 | } |
819 | | |
820 | | /* |
821 | | * Get compile-time information for libraries used by libwireshark. |
822 | | */ |
823 | | void |
824 | | epan_gather_compile_info(feature_list l) |
825 | 14 | { |
826 | 14 | gather_zlib_compile_info(l); |
827 | 14 | gather_zlib_ng_compile_info(l); |
828 | 14 | gather_pcre2_compile_info(l); |
829 | | |
830 | | /* Lua */ |
831 | | #ifdef HAVE_LUA |
832 | | #ifdef HAVE_LUA_UNICODE |
833 | | with_feature(l, "%s", LUA_RELEASE" (UfW patched)"); |
834 | | #else /* HAVE_LUA_UNICODE */ |
835 | | with_feature(l, "%s", LUA_RELEASE); |
836 | | #endif /* HAVE_LUA_UNICODE */ |
837 | | #else /* HAVE_LUA */ |
838 | 14 | without_feature(l, "Lua"); |
839 | 14 | #endif /* HAVE_LUA */ |
840 | | |
841 | | /* GnuTLS */ |
842 | | #ifdef HAVE_LIBGNUTLS |
843 | | #ifdef HAVE_GNUTLS_PKCS11 |
844 | | with_feature(l, "GnuTLS %s and PKCS#11", LIBGNUTLS_VERSION); |
845 | | #else |
846 | | with_feature(l, "GnuTLS %s", LIBGNUTLS_VERSION); |
847 | | #endif /* HAVE_GNUTLS_PKCS11 */ |
848 | | #else |
849 | 14 | without_feature(l, "GnuTLS"); |
850 | 14 | #endif /* HAVE_LIBGNUTLS */ |
851 | | |
852 | | /* Gcrypt */ |
853 | 14 | with_feature(l, "Gcrypt %s", GCRYPT_VERSION); |
854 | | |
855 | | /* Kerberos */ |
856 | | #if defined(HAVE_MIT_KERBEROS) |
857 | | with_feature(l, "Kerberos (MIT)"); |
858 | | #elif defined(HAVE_HEIMDAL_KERBEROS) |
859 | | with_feature(l, "Kerberos (Heimdal)"); |
860 | | #else |
861 | 14 | without_feature(l, "Kerberos"); |
862 | 14 | #endif /* HAVE_KERBEROS */ |
863 | | |
864 | | /* MaxMindDB */ |
865 | | #ifdef HAVE_MAXMINDDB |
866 | | with_feature(l, "MaxMind %s", MAXMINDDB_VERSION); |
867 | | #else |
868 | 14 | without_feature(l, "MaxMind"); |
869 | 14 | #endif /* HAVE_MAXMINDDB */ |
870 | | |
871 | | /* nghttp2 */ |
872 | | #ifdef HAVE_NGHTTP2 |
873 | | with_feature(l, "nghttp2 %s", NGHTTP2_VERSION); |
874 | | #else |
875 | 14 | without_feature(l, "nghttp2"); |
876 | 14 | #endif /* HAVE_NGHTTP2 */ |
877 | | |
878 | | /* nghttp3 */ |
879 | | #ifdef HAVE_NGHTTP3 |
880 | | with_feature(l, "nghttp3 %s", NGHTTP3_VERSION); |
881 | | #else |
882 | 14 | without_feature(l, "nghttp3"); |
883 | 14 | #endif /* HAVE_NGHTTP3 */ |
884 | | |
885 | | /* brotli */ |
886 | | #ifdef HAVE_BROTLI |
887 | | with_feature(l, "brotli"); |
888 | | #else |
889 | 14 | without_feature(l, "brotli"); |
890 | 14 | #endif /* HAVE_BROTLI */ |
891 | | |
892 | | /* LZ4 */ |
893 | | #ifdef HAVE_LZ4 |
894 | | with_feature(l, "LZ4 %s", LZ4_VERSION_STRING); |
895 | | #else |
896 | 14 | without_feature(l, "LZ4"); |
897 | 14 | #endif /* HAVE_LZ4 */ |
898 | | |
899 | | /* Zstandard */ |
900 | | #ifdef HAVE_ZSTD |
901 | | with_feature(l, "Zstandard %s", ZSTD_VERSION_STRING); |
902 | | #else |
903 | 14 | without_feature(l, "Zstandard"); |
904 | 14 | #endif /* HAVE_ZSTD */ |
905 | | |
906 | | /* Snappy */ |
907 | | #ifdef HAVE_SNAPPY |
908 | | /* |
909 | | * snappy-stubs-public.h defines SNAPPY_MAJOR, SNAPPY_MINOR, |
910 | | * and SNAPPY_PATCHLEVEL, but it's a C++-only header. |
911 | | */ |
912 | | with_feature(l, "Snappy %s", SNAPPY_VERSION); |
913 | | #else |
914 | 14 | without_feature(l, "Snappy"); |
915 | 14 | #endif /* HAVE_SNAPPY */ |
916 | | |
917 | | /* libxml2 */ |
918 | | #ifdef HAVE_LIBXML2 |
919 | | with_feature(l, "libxml2 %s", LIBXML_DOTTED_VERSION); |
920 | | #else |
921 | 14 | without_feature(l, "libxml2"); |
922 | 14 | #endif /* HAVE_LIBXML2 */ |
923 | | |
924 | | /* libsmi */ |
925 | | #ifdef HAVE_LIBSMI |
926 | | with_feature(l, "libsmi %s", SMI_VERSION_STRING); |
927 | | #else |
928 | 14 | without_feature(l, "libsmi"); |
929 | 14 | #endif /* HAVE_LIBSMI */ |
930 | 14 | } |
931 | | |
932 | | /* |
933 | | * Get runtime information for libraries used by libwireshark. |
934 | | */ |
935 | | void |
936 | | epan_gather_runtime_info(feature_list l) |
937 | 14 | { |
938 | 14 | gather_zlib_runtime_info(l); |
939 | 14 | gather_pcre2_runtime_info(l); |
940 | | |
941 | | /* c-ares */ |
942 | 14 | with_feature(l, "c-ares %s", ares_version(NULL)); |
943 | | |
944 | | /* GnuTLS */ |
945 | | #ifdef HAVE_LIBGNUTLS |
946 | | with_feature(l, "GnuTLS %s", gnutls_check_version(NULL)); |
947 | | #endif /* HAVE_LIBGNUTLS */ |
948 | | |
949 | | /* Gcrypt */ |
950 | 14 | with_feature(l, "Gcrypt %s", gcry_check_version(NULL)); |
951 | | |
952 | | /* nghttp2 */ |
953 | | #if NGHTTP2_VERSION_AGE >= 1 |
954 | | nghttp2_info *nghttp2_ptr = nghttp2_version(0); |
955 | | with_feature(l, "nghttp2 %s", nghttp2_ptr->version_str); |
956 | | #endif /* NGHTTP2_VERSION_AGE */ |
957 | | |
958 | | /* nghttp3 */ |
959 | | #if NGHTTP3_VERSION_AGE >= 1 |
960 | | const nghttp3_info *nghttp3_ptr = nghttp3_version(0); |
961 | | with_feature(l, "nghttp3 %s", nghttp3_ptr->version_str); |
962 | | #endif /* NGHTTP3_VERSION_AGE */ |
963 | | |
964 | | /* brotli */ |
965 | | #ifdef HAVE_BROTLI |
966 | | with_feature(l, "brotli %d.%d.%d", BrotliDecoderVersion() >> 24, |
967 | | (BrotliDecoderVersion() >> 12) & 0xFFF, BrotliDecoderVersion() & 0xFFF); |
968 | | #endif |
969 | | |
970 | | /* LZ4 */ |
971 | | #ifdef HAVE_LZ4 |
972 | | with_feature(l, "LZ4 %s", LZ4_versionString()); |
973 | | #endif /* HAVE_LZ4 */ |
974 | | |
975 | | /* Zstandard */ |
976 | | #if ZSTD_VERSION_NUMBER >= 10300 |
977 | | with_feature(l, "Zstandard %s", ZSTD_versionString()); |
978 | | #endif /* ZSTD_VERSION_NUMBER */ |
979 | | |
980 | | /* libsmi */ |
981 | | #ifdef HAVE_SMI_VERSION_STRING |
982 | | with_feature(l, "libsmi %s", smi_version_string); |
983 | | #endif /* HAVE_SMI_VERSION_STRING */ |
984 | 14 | } |
985 | | |
986 | | /* |
987 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
988 | | * |
989 | | * Local variables: |
990 | | * c-basic-offset: 8 |
991 | | * tab-width: 8 |
992 | | * indent-tabs-mode: t |
993 | | * End: |
994 | | * |
995 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
996 | | * :indentSize=8:tabSize=8:noTabs=false: |
997 | | */ |