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