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