wsgcrypt.h checks internally if we HAVE_LIBGCRYPT
[metze/wireshark/wip.git] / epan / epan.c
index b3580200ba2c87131a3fc50e8b3c36cff8483437..b2a1f5d4f64e0fdc219f0158c9c07c735136fa59 100644 (file)
@@ -1,6 +1,4 @@
 /* epan.c
- *
- * $Id$
  *
  * Wireshark Protocol Analyzer Library
  *
 
 #include "config.h"
 
-#ifdef HAVE_PYTHON
-#include <Python.h> /* to get the Python version number (PY_VERSION) */
-#endif
+#include <stdarg.h>
 
-#ifdef HAVE_LIBGCRYPT
 #include <wsutil/wsgcrypt.h>
-#endif /* HAVE_LIBGCRYPT */
 
 #ifdef HAVE_LIBGNUTLS
 #include <gnutls/gnutls.h>
 #endif /* HAVE_LIBGNUTLS */
 
 #include <glib.h>
+
+#include <wsutil/report_err.h>
+
+#include <epan/exceptions.h>
+
 #include "epan-int.h"
 #include "epan.h"
+#include "dfilter/dfilter.h"
 #include "epan_dissect.h"
-#include "wsutil/report_err.h"
 
 #include "conversation.h"
 #include "circuit.h"
@@ -50,9 +49,9 @@
 #include "tap.h"
 #include "addr_resolv.h"
 #include "oids.h"
-#include "emem.h"
 #include "wmem/wmem.h"
 #include "expert.h"
+#include "print.h"
 
 #ifdef HAVE_LUA
 #include <lua.h>
 #include <ares_version.h>
 #endif
 
+static wmem_allocator_t *pinfo_pool_cache = NULL;
+
 const gchar*
 epan_get_version(void) {
        return VERSION;
 }
 
+/*
+ * Register all the plugin types that are part of libwireshark, namely
+ * dissector and tap plugins.
+ *
+ * Must be called before init_plugins(), which must be called before
+ * any registration routines are called.
+ */
 void
+epan_register_plugin_types(void)
+{
+#ifdef HAVE_PLUGINS
+       register_dissector_plugin_type();
+       register_tap_plugin_type();
+#endif
+}
+
+gboolean
 epan_init(void (*register_all_protocols_func)(register_cb cb, gpointer client_data),
          void (*register_all_handoffs_func)(register_cb cb, gpointer client_data),
          register_cb cb,
-         gpointer client_data,
-         void (*report_failure_fcn_p)(const char *, va_list),
-         void (*report_open_failure_fcn_p)(const char *, int, gboolean),
-         void (*report_read_failure_fcn_p)(const char *, int),
-         void (*report_write_failure_fcn_p)(const char *, int))
+         gpointer client_data)
 {
-       init_report_err(report_failure_fcn_p, report_open_failure_fcn_p,
-           report_read_failure_fcn_p, report_write_failure_fcn_p);
+       volatile gboolean status = TRUE;
 
-       /* initialize memory allocation subsystems */
-       emem_init();
+       /* initialize memory allocation subsystem */
        wmem_init();
 
        /* initialize the GUID to name mapping table */
        guids_init();
 
-        /* initialize name resolution (addr_resolv.c) */
-        addr_resolv_init();
+       /* initialize name resolution (addr_resolv.c) */
+       addr_resolv_init();
 
        except_init();
 #ifdef HAVE_LIBGCRYPT
@@ -105,19 +116,42 @@ epan_init(void (*register_all_protocols_func)(register_cb cb, gpointer client_da
 #ifdef HAVE_LIBGNUTLS
        gnutls_global_init();
 #endif
-       tap_init();
-       prefs_init();
-       expert_init();
-       packet_init();
-       proto_init(register_all_protocols_func, register_all_handoffs_func,
-           cb, client_data);
-       packet_cache_proto_handles();
-       dfilter_init();
-       final_registration_all_protocols();
-       expert_packet_init();
+       TRY {
+               tap_init();
+               prefs_init();
+               expert_init();
+               packet_init();
+               proto_init(register_all_protocols_func, register_all_handoffs_func,
+                   cb, client_data);
+               packet_cache_proto_handles();
+               dfilter_init();
+               final_registration_all_protocols();
+               print_cache_field_handles();
+               expert_packet_init();
 #ifdef HAVE_LUA
-       wslua_init(cb, client_data);
+               wslua_init(cb, client_data);
 #endif
+       }
+       CATCH(DissectorError) {
+               /*
+                * This is probably a dissector, or something it calls,
+                * calling REPORT_DISSECTOR_ERROR() in a registration
+                * routine or something else outside the normal dissection
+                * code path.
+                */
+               const char *exception_message = GET_MESSAGE;
+               static const char dissector_error_nomsg[] =
+                   "Dissector writer didn't bother saying what the error was";
+
+               report_failure("Dissector bug: %s",
+                              exception_message == NULL ?
+                                dissector_error_nomsg : exception_message);
+               if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
+                       abort();
+               status = FALSE;
+       }
+       ENDTRY;
+       return status;
 }
 
 void
@@ -128,11 +162,20 @@ epan_cleanup(void)
        prefs_cleanup();
        packet_cleanup();
        expert_cleanup();
+#ifdef HAVE_LUA
+       wslua_cleanup();
+#endif
 #ifdef HAVE_LIBGNUTLS
        gnutls_global_deinit();
 #endif
        except_deinit();
        addr_resolv_cleanup();
+
+       if (pinfo_pool_cache != NULL) {
+               wmem_destroy_allocator(pinfo_pool_cache);
+               pinfo_pool_cache = NULL;
+       }
+
        wmem_cleanup();
 }
 
@@ -214,6 +257,21 @@ epan_circuit_cleanup(void)
        circuit_cleanup();
 }
 
+/* Overrides proto_tree_visible i epan_dissect_init to make all fields visible.
+ * This is > 0 if a Lua script wanted to see all fields all the time.
+ * This is ref-counted, so clearing it won't override other taps/scripts wanting it.
+ */
+static gint always_visible_refcount = 0;
+
+void
+epan_set_always_visible(gboolean force)
+{
+       if (force)
+               always_visible_refcount++;
+       else if (always_visible_refcount > 0)
+               always_visible_refcount--;
+}
+
 epan_dissect_t*
 epan_dissect_init(epan_dissect_t *edt, epan_t *session, const gboolean create_proto_tree, const gboolean proto_tree_visible)
 {
@@ -221,9 +279,18 @@ epan_dissect_init(epan_dissect_t *edt, epan_t *session, const gboolean create_pr
 
        edt->session = session;
 
+       memset(&edt->pi, 0, sizeof(edt->pi));
+       if (pinfo_pool_cache != NULL) {
+               edt->pi.pool = pinfo_pool_cache;
+               pinfo_pool_cache = NULL;
+       }
+       else {
+               edt->pi.pool = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK_FAST);
+       }
+
        if (create_proto_tree) {
                edt->tree = proto_tree_create_root(&edt->pi);
-               proto_tree_set_visible(edt->tree, proto_tree_visible);
+               proto_tree_set_visible(edt->tree, (always_visible_refcount > 0) ? TRUE : proto_tree_visible);
        }
        else {
                edt->tree = NULL;
@@ -231,9 +298,6 @@ epan_dissect_init(epan_dissect_t *edt, epan_t *session, const gboolean create_pr
 
        edt->tvb = NULL;
 
-       memset(&edt->pi, 0, sizeof(edt->pi));
-       edt->pi.pool = wmem_allocator_new(WMEM_ALLOCATOR_SIMPLE);
-
        return edt;
 }
 
@@ -245,6 +309,7 @@ epan_dissect_reset(epan_dissect_t *edt)
 
        g_assert(edt);
 
+       g_slist_free(edt->pi.proto_data);
        g_slist_free(edt->pi.dependent_frames);
 
        /* Free the data sources list. */
@@ -284,31 +349,58 @@ epan_dissect_fake_protocols(epan_dissect_t *edt, const gboolean fake_protocols)
 }
 
 void
-epan_dissect_run(epan_dissect_t *edt, struct wtap_pkthdr *phdr,
-        tvbuff_t *tvb, frame_data *fd, column_info *cinfo)
+epan_dissect_run(epan_dissect_t *edt, int file_type_subtype,
+       struct wtap_pkthdr *phdr, tvbuff_t *tvb, frame_data *fd,
+       column_info *cinfo)
 {
 #ifdef HAVE_LUA
        wslua_prime_dfilter(edt); /* done before entering wmem scope */
 #endif
        wmem_enter_packet_scope();
-       dissect_packet(edt, phdr, tvb, fd, cinfo);
+       dissect_record(edt, file_type_subtype, phdr, tvb, fd, cinfo);
 
        /* free all memory allocated */
-       ep_free_all();
        wmem_leave_packet_scope();
 }
 
 void
-epan_dissect_run_with_taps(epan_dissect_t *edt, struct wtap_pkthdr *phdr,
-        tvbuff_t *tvb, frame_data *fd, column_info *cinfo)
+epan_dissect_run_with_taps(epan_dissect_t *edt, int file_type_subtype,
+       struct wtap_pkthdr *phdr, tvbuff_t *tvb, frame_data *fd,
+       column_info *cinfo)
 {
        wmem_enter_packet_scope();
        tap_queue_init(edt);
-       dissect_packet(edt, phdr, tvb, fd, cinfo);
+       dissect_record(edt, file_type_subtype, phdr, tvb, fd, cinfo);
+       tap_push_tapped_queue(edt);
+
+       /* free all memory allocated */
+       wmem_leave_packet_scope();
+}
+
+void
+epan_dissect_file_run(epan_dissect_t *edt, struct wtap_pkthdr *phdr,
+       tvbuff_t *tvb, frame_data *fd, column_info *cinfo)
+{
+#ifdef HAVE_LUA
+       wslua_prime_dfilter(edt); /* done before entering wmem scope */
+#endif
+       wmem_enter_packet_scope();
+       dissect_file(edt, phdr, tvb, fd, cinfo);
+
+       /* free all memory allocated */
+       wmem_leave_packet_scope();
+}
+
+void
+epan_dissect_file_run_with_taps(epan_dissect_t *edt, struct wtap_pkthdr *phdr,
+       tvbuff_t *tvb, frame_data *fd, column_info *cinfo)
+{
+       wmem_enter_packet_scope();
+       tap_queue_init(edt);
+       dissect_file(edt, phdr, tvb, fd, cinfo);
        tap_push_tapped_queue(edt);
 
        /* free all memory allocated */
-       ep_free_all();
        wmem_leave_packet_scope();
 }
 
@@ -317,6 +409,7 @@ epan_dissect_cleanup(epan_dissect_t* edt)
 {
        g_assert(edt);
 
+       g_slist_free(edt->pi.proto_data);
        g_slist_free(edt->pi.dependent_frames);
 
        /* Free the data sources list. */
@@ -331,7 +424,13 @@ epan_dissect_cleanup(epan_dissect_t* edt)
                proto_tree_free(edt->tree);
        }
 
-       wmem_destroy_allocator(edt->pi.pool);
+       if (pinfo_pool_cache == NULL) {
+               wmem_free_all(edt->pi.pool);
+               pinfo_pool_cache = edt->pi.pool;
+       }
+       else {
+               wmem_destroy_allocator(edt->pi.pool);
+       }
 }
 
 void
@@ -349,38 +448,38 @@ epan_dissect_prime_dfilter(epan_dissect_t *edt, const dfilter_t* dfcode)
 
 /* ----------------------- */
 const gchar *
-epan_custom_set(epan_dissect_t *edt, int field_id,
-                             gint occurrence,
-                             gchar *result,
-                             gchar *expr, const int size )
+epan_custom_set(epan_dissect_t *edt, GSList *field_ids,
+                            gint occurrence,
+                            gchar *result,
+                            gchar *expr, const int size )
 {
-    return proto_custom_set(edt->tree, field_id, occurrence, result, expr, size);
+       return proto_custom_set(edt->tree, field_ids, occurrence, result, expr, size);
 }
 
 void
 epan_dissect_fill_in_columns(epan_dissect_t *edt, const gboolean fill_col_exprs, const gboolean fill_fd_colums)
 {
-    col_custom_set_edt(edt, edt->pi.cinfo);
-    col_fill_in(&edt->pi, fill_col_exprs, fill_fd_colums);
+       col_custom_set_edt(edt, edt->pi.cinfo);
+       col_fill_in(&edt->pi, fill_col_exprs, fill_fd_colums);
 }
 
 gboolean
 epan_dissect_packet_contains_field(epan_dissect_t* edt,
-                                   const char *field_name)
+                                  const char *field_name)
 {
-    GPtrArray* array;
-    int        field_id;
-    gboolean   contains_field;
-
-    if (!edt || !edt->tree)
-        return FALSE;
-    field_id = proto_get_id_by_filter_name(field_name);
-    if (field_id < 0)
-        return FALSE;
-    array = proto_find_finfo(edt->tree, field_id);
-    contains_field = (array->len > 0) ? TRUE : FALSE;
-    g_ptr_array_free(array, TRUE);
-    return contains_field;
+       GPtrArray* array;
+       int field_id;
+       gboolean contains_field;
+
+       if (!edt || !edt->tree)
+               return FALSE;
+       field_id = proto_get_id_by_filter_name(field_name);
+       if (field_id < 0)
+               return FALSE;
+       array = proto_find_finfo(edt->tree, field_id);
+       contains_field = (array->len > 0) ? TRUE : FALSE;
+       g_ptr_array_free(array, TRUE);
+       return contains_field;
 }
 
 /*
@@ -389,7 +488,7 @@ epan_dissect_packet_contains_field(epan_dissect_t* edt,
 void
 epan_get_compiled_version_info(GString *str)
 {
-        /* SNMP */
+       /* SNMP */
        g_string_append(str, ", ");
 #ifdef HAVE_LIBSMI
        g_string_append(str, "with SMI " SMI_VERSION_STRING);
@@ -413,7 +512,7 @@ epan_get_compiled_version_info(GString *str)
 #endif /* HAVE_GNU_ADNS */
 #endif /* HAVE_C_ARES */
 
-        /* LUA */
+       /* LUA */
        g_string_append(str, ", ");
 #ifdef HAVE_LUA
        g_string_append(str, "with ");
@@ -422,17 +521,7 @@ epan_get_compiled_version_info(GString *str)
        g_string_append(str, "without Lua");
 #endif /* HAVE_LUA */
 
-       g_string_append(str, ", ");
-#ifdef HAVE_PYTHON
-       g_string_append(str, "with Python");
-#ifdef PY_VERSION
-       g_string_append(str, " " PY_VERSION);
-#endif /* PY_VERSION */
-#else
-       g_string_append(str, "without Python");
-#endif /* HAVE_PYTHON */
-
-        /* GnuTLS */
+       /* GnuTLS */
        g_string_append(str, ", ");
 #ifdef HAVE_LIBGNUTLS
        g_string_append(str, "with GnuTLS " LIBGNUTLS_VERSION);
@@ -440,7 +529,7 @@ epan_get_compiled_version_info(GString *str)
        g_string_append(str, "without GnuTLS");
 #endif /* HAVE_LIBGNUTLS */
 
-        /* Gcrypt */
+       /* Gcrypt */
        g_string_append(str, ", ");
 #ifdef HAVE_LIBGCRYPT
        g_string_append(str, "with Gcrypt " GCRYPT_VERSION);
@@ -448,14 +537,14 @@ epan_get_compiled_version_info(GString *str)
        g_string_append(str, "without Gcrypt");
 #endif /* HAVE_LIBGCRYPT */
 
-        /* Kerberos */
-        /* XXX - I don't see how to get the version number, at least for KfW */
+       /* Kerberos */
+       /* XXX - I don't see how to get the version number, at least for KfW */
        g_string_append(str, ", ");
 #ifdef HAVE_KERBEROS
 #ifdef HAVE_MIT_KERBEROS
        g_string_append(str, "with MIT Kerberos");
 #else
-        /* HAVE_HEIMDAL_KERBEROS */
+       /* HAVE_HEIMDAL_KERBEROS */
        g_string_append(str, "with Heimdal Kerberos");
 #endif
 #else
@@ -482,14 +571,14 @@ _U_
 #endif
 )
 {
-        /* GnuTLS */
+       /* GnuTLS */
 #ifdef HAVE_LIBGNUTLS
-       g_string_append_printf(str, ", GnuTLS %s", gnutls_check_version(NULL));
+       g_string_append_printf(str, ", with GnuTLS %s", gnutls_check_version(NULL));
 #endif /* HAVE_LIBGNUTLS */
 
-        /* Gcrypt */
+       /* Gcrypt */
 #ifdef HAVE_LIBGCRYPT
-       g_string_append_printf(str, ", Gcrypt %s", gcry_check_version(NULL));
+       g_string_append_printf(str, ", with Gcrypt %s", gcry_check_version(NULL));
 #endif /* HAVE_LIBGCRYPT */
 }