ISO14443: Fix Dead Store (Dead assignement/Dead increment) Warning found by Clang
[metze/wireshark/wip.git] / epan / epan.c
index e3a63175b3dbf74562ea7edbc4a5a0bafc0b266a..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 "report_err.h"
 
 #include "conversation.h"
 #include "circuit.h"
@@ -49,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();
+
        except_init();
 #ifdef HAVE_LIBGCRYPT
        /* initialize libgcrypt (beware, it won't be thread-safe) */
@@ -101,37 +116,123 @@ epan_init(void (*register_all_protocols_func)(register_cb cb, gpointer client_da
 #ifdef HAVE_LIBGNUTLS
        gnutls_global_init();
 #endif
-       tap_init();
-       prefs_init();
-       proto_init(register_all_protocols_func, register_all_handoffs_func,
-           cb, client_data);
-       packet_init();
-       dfilter_init();
-       final_registration_all_protocols();
-       /*host_name_lookup_init();*//* We load the hostname file in cf_open, no need to do it here? */
-       expert_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
 epan_cleanup(void)
 {
-       cleanup_dissection();
        dfilter_cleanup();
        proto_cleanup();
        prefs_cleanup();
        packet_cleanup();
-       oid_resolv_cleanup();
+       expert_cleanup();
+#ifdef HAVE_LUA
+       wslua_cleanup();
+#endif
 #ifdef HAVE_LIBGNUTLS
        gnutls_global_deinit();
 #endif
        except_deinit();
-       host_name_lookup_cleanup();
+       addr_resolv_cleanup();
+
+       if (pinfo_pool_cache != NULL) {
+               wmem_destroy_allocator(pinfo_pool_cache);
+               pinfo_pool_cache = NULL;
+       }
+
        wmem_cleanup();
 }
 
+epan_t *
+epan_new(void)
+{
+       epan_t *session = g_slice_new(epan_t);
+
+       /* XXX, it should take session as param */
+       init_dissection();
+
+       return session;
+}
+
+const char *
+epan_get_user_comment(const epan_t *session, const frame_data *fd)
+{
+       if (session->get_user_comment)
+               return session->get_user_comment(session->data, fd);
+
+       return NULL;
+}
+
+const char *
+epan_get_interface_name(const epan_t *session, guint32 interface_id)
+{
+       if (session->get_interface_name)
+               return session->get_interface_name(session->data, interface_id);
+
+       return NULL;
+}
+
+const nstime_t *
+epan_get_frame_ts(const epan_t *session, guint32 frame_num)
+{
+       const nstime_t *abs_ts = NULL;
+
+       if (session->get_frame_ts)
+               abs_ts = session->get_frame_ts(session->data, frame_num);
+
+       if (!abs_ts)
+               g_warning("!!! couldn't get frame ts for %u !!!\n", frame_num);
+
+       return abs_ts;
+}
+
+void
+epan_free(epan_t *session)
+{
+       if (session) {
+               /* XXX, it should take session as param */
+               cleanup_dissection();
+
+               g_slice_free(epan_t, session);
+       }
+}
+
 void
 epan_conversation_init(void)
 {
@@ -156,34 +257,88 @@ 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, const gboolean create_proto_tree, const gboolean proto_tree_visible)
+epan_dissect_init(epan_dissect_t *edt, epan_t *session, const gboolean create_proto_tree, const gboolean proto_tree_visible)
 {
        g_assert(edt);
 
-       edt->pi.pool = wmem_allocator_new(WMEM_ALLOCATOR_SIMPLE);
+       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;
        }
 
-       edt->pi.dependent_frames = NULL;
+       edt->tvb = NULL;
 
        return edt;
 }
 
+void
+epan_dissect_reset(epan_dissect_t *edt)
+{
+       /* We have to preserve the pool pointer across the memzeroing */
+       wmem_allocator_t *tmp;
+
+       g_assert(edt);
+
+       g_slist_free(edt->pi.proto_data);
+       g_slist_free(edt->pi.dependent_frames);
+
+       /* Free the data sources list. */
+       free_data_sources(&edt->pi);
+
+       if (edt->tvb) {
+               /* Free all tvb's chained from this tvb */
+               tvb_free_chain(edt->tvb);
+               edt->tvb = NULL;
+       }
+
+       if (edt->tree)
+               proto_tree_reset(edt->tree);
+
+       tmp = edt->pi.pool;
+       wmem_free_all(tmp);
+
+       memset(&edt->pi, 0, sizeof(edt->pi));
+       edt->pi.pool = tmp;
+}
+
 epan_dissect_t*
-epan_dissect_new(const gboolean create_proto_tree, const gboolean proto_tree_visible)
+epan_dissect_new(epan_t *session, const gboolean create_proto_tree, const gboolean proto_tree_visible)
 {
        epan_dissect_t *edt;
 
        edt = g_new0(epan_dissect_t, 1);
 
-       return epan_dissect_init(edt, create_proto_tree, proto_tree_visible);
+       return epan_dissect_init(edt, session, create_proto_tree, proto_tree_visible);
 }
 
 void
@@ -194,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,
-        const guint8* data, 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, data, 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,
-        const guint8* data, 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, data, 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();
 }
 
@@ -227,19 +409,28 @@ 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. */
        free_data_sources(&edt->pi);
 
-       /* Free all tvb's chained from this tvb */
-       tvb_free_chain(edt->tvb);
+       if (edt->tvb) {
+               /* Free all tvb's chained from this tvb */
+               tvb_free_chain(edt->tvb);
+       }
 
        if (edt->tree) {
                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
@@ -257,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;
 }
 
 /*
@@ -297,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);
@@ -321,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 ");
@@ -330,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);
@@ -348,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);
@@ -356,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
@@ -390,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 */
 }