MAX_MCS_INDEX is a valid array index.
[metze/wireshark/wip.git] / epan / oids.c
index 3935f41df1fa9ed160c05f66a9e4e5e0b000e456..9d14838fc8f5b9e98671bd53dc8d3f05086e0b88 100644 (file)
@@ -3,8 +3,6 @@
  *
  * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
  *
- * $Id$
- *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #include <glib.h>
 #include <stdio.h>
 #include <string.h>
-#include <ctype.h>
 
-#include "emem.h"
+#include <wsutil/report_err.h>
+
+#include "wmem/wmem.h"
 #include "uat.h"
 #include "prefs.h"
 #include "proto.h"
 #include "packet.h"
-#include "report_err.h"
-#include "filesystem.h"
+#include "wsutil/filesystem.h"
 #include "dissectors/packet-ber.h"
 
 #ifdef HAVE_LIBSMI
 #include <smi.h>
+
+static gboolean oids_init_done = FALSE;
+static gboolean load_smi_modules = FALSE;
+static gboolean suppress_smi_errors = FALSE;
 #endif
 
 #define D(level,args) do if (debuglevel >= level) { printf args; printf("\n"); fflush(stdout); } while(0)
 
 static int debuglevel = 0;
 
+/*
+ * From SNMPv2-SMI and X.690
+ *
+ * Counter32  ::= [APPLICATION 1] IMPLICIT INTEGER (0..4294967295)
+ * Gauge32    ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295)
+ * Unsigned32 ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) (alias of Gauge32)
+ * TimeTicks  ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
+ *
+ * If the BER encoding should not have the top bit set as to not become a negative number
+ * the BER encoding may take 5 octets to encode.
+ */
+
+#ifdef HAVE_LIBSMI
 static const oid_value_type_t integer_type =    { FT_INT32,  BASE_DEC,  BER_CLASS_UNI, BER_UNI_TAG_INTEGER,     1,   4, OID_KEY_TYPE_INTEGER, 1};
 static const oid_value_type_t bytes_type =      { FT_BYTES,  BASE_NONE, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 0,  -1, OID_KEY_TYPE_BYTES,   0};
 static const oid_value_type_t oid_type =        { FT_OID,    BASE_NONE, BER_CLASS_UNI, BER_UNI_TAG_OID,         1,  -1, OID_KEY_TYPE_OID,     0};
 static const oid_value_type_t ipv4_type =       { FT_IPv4,   BASE_NONE, BER_CLASS_APP, 0,                       4,   4, OID_KEY_TYPE_IPADDR,  4};
 static const oid_value_type_t counter32_type =  { FT_UINT64, BASE_DEC,  BER_CLASS_APP, 1,                       1,   5, OID_KEY_TYPE_INTEGER, 1};
-static const oid_value_type_t unsigned32_type = { FT_UINT32, BASE_DEC,  BER_CLASS_APP, 2,                       1,   4, OID_KEY_TYPE_INTEGER, 1};
-/*static const oid_value_type_t timeticks_type =  { FT_UINT32, BASE_DEC,  BER_CLASS_APP, 3,                       1,   4, OID_KEY_TYPE_INTEGER, 1};
- * TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
- * If the BER encoding should not have the top bit set as to not become a negative number
- * the ber encoding may take 5 octets to encode.
- */
+static const oid_value_type_t unsigned32_type = { FT_UINT64, BASE_DEC,  BER_CLASS_APP, 2,                       1,   5, OID_KEY_TYPE_INTEGER, 1};
 static const oid_value_type_t timeticks_type =  { FT_UINT64, BASE_DEC,  BER_CLASS_APP, 3,                       1,   5, OID_KEY_TYPE_INTEGER, 1};
+#if 0
 static const oid_value_type_t opaque_type =     { FT_BYTES,  BASE_NONE, BER_CLASS_APP, 4,                       1,   4, OID_KEY_TYPE_BYTES,   0};
+#endif
 static const oid_value_type_t nsap_type =       { FT_BYTES,  BASE_NONE, BER_CLASS_APP, 5,                       0,  -1, OID_KEY_TYPE_NSAP,    0};
 static const oid_value_type_t counter64_type =  { FT_UINT64, BASE_DEC,  BER_CLASS_APP, 6,                       1,   8, OID_KEY_TYPE_INTEGER, 1};
 static const oid_value_type_t ipv6_type =       { FT_IPv6,   BASE_NONE, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 16, 16, OID_KEY_TYPE_BYTES,   16};
@@ -72,21 +82,21 @@ static const oid_value_type_t float_type =      { FT_FLOAT,  BASE_DEC,  BER_CLAS
 static const oid_value_type_t double_type =     { FT_DOUBLE, BASE_DEC,  BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 8,   8, OID_KEY_TYPE_WRONG,   0};
 static const oid_value_type_t ether_type =      { FT_ETHER,  BASE_NONE, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 6,   6, OID_KEY_TYPE_ETHER,   6};
 static const oid_value_type_t string_type =     { FT_STRING, BASE_NONE, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 0,  -1, OID_KEY_TYPE_STRING,  0};
+static const oid_value_type_t date_and_time_type = { FT_STRING,  BASE_NONE, BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 8,  11, OID_KEY_TYPE_DATE_AND_TIME,   0};
+#endif /* HAVE_LIBSMI */
+
 static const oid_value_type_t unknown_type =    { FT_BYTES,  BASE_NONE, BER_CLASS_ANY, BER_TAG_ANY,             0,  -1, OID_KEY_TYPE_WRONG,   0};
 
 static oid_info_t oid_root = { 0, NULL, OID_KIND_UNKNOWN, NULL, &unknown_type, -2, NULL, NULL, NULL};
 
-static oid_info_t* add_oid(const char* name, oid_kind_t kind, const oid_value_type_t* type, oid_key_t* key, guint oid_len, guint32 *subids) {
-       guint i = 0;
-       oid_info_t* c = &oid_root;
-
+static void prepopulate_oids(void) {
        if (!oid_root.children) {
                char* debug_env = getenv("WIRESHARK_DEBUG_MIBS");
                guint32 subid;
 
-               debuglevel = debug_env ? strtoul(debug_env,NULL,10) : 0;
+               debuglevel = debug_env ? (int)strtoul(debug_env,NULL,10) : 0;
 
-               oid_root.children = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_root");
+               oid_root.children = wmem_tree_new(wmem_epan_scope());
 
                /*
                 * make sure we got strings at least in the three root-children oids
@@ -96,11 +106,19 @@ static oid_info_t* add_oid(const char* name, oid_kind_t kind, const oid_value_ty
                subid = 1; oid_add("iso",1,&subid);
                subid = 2; oid_add("joint-iso-itu-t",1,&subid);
        }
+}
+
 
+
+static oid_info_t* add_oid(const char* name, oid_kind_t kind, const oid_value_type_t* type, oid_key_t* key, guint oid_len, guint32 *subids) {
+       guint i = 0;
+       oid_info_t* c = &oid_root;
+
+       prepopulate_oids();
        oid_len--;
 
        do {
-               oid_info_t* n = emem_tree_lookup32(c->children,subids[i]);
+               oid_info_t* n = (oid_info_t *)wmem_tree_lookup32(c->children,subids[i]);
 
                if(n) {
                        if (i == oid_len) {
@@ -108,11 +126,10 @@ static oid_info_t* add_oid(const char* name, oid_kind_t kind, const oid_value_ty
                                        if (!g_str_equal(n->name,name)) {
                                                D(2,("Renaming Oid from: %s -> %s, this means the same oid is registered more than once",n->name,name));
                                        }
-                                       /* XXX - Don't free n->name here. It may be part of an hf_register_info
-                                         * struct that has been appended to the hfa GArray. */
+                                       wmem_free(wmem_epan_scope(), n->name);
                                }
 
-                               n->name = g_strdup(name);
+                               n->name = wmem_strdup(wmem_epan_scope(), name);
 
                                if (! n->value_type) {
                                        n->value_type = type;
@@ -121,19 +138,19 @@ static oid_info_t* add_oid(const char* name, oid_kind_t kind, const oid_value_ty
                                return n;
                        }
                } else {
-                       n = g_malloc(sizeof(oid_info_t));
+                       n = wmem_new(wmem_epan_scope(), oid_info_t);
                        n->subid = subids[i];
                        n->kind = kind;
-                       n->children = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_children");
+                       n->children = wmem_tree_new(wmem_epan_scope());
                        n->value_hfid = -2;
                        n->key = key;
                        n->parent = c;
                        n->bits = NULL;
 
-                       emem_tree_insert32(c->children,n->subid,n);
+                       wmem_tree_insert32(c->children,n->subid,n);
 
                        if (i == oid_len) {
-                               n->name = g_strdup(name);
+                               n->name = wmem_strdup(wmem_epan_scope(), name);
                                n->value_type = type;
                                n->kind = kind;
                                return n;
@@ -153,8 +170,10 @@ static oid_info_t* add_oid(const char* name, oid_kind_t kind, const oid_value_ty
 void oid_add(const char* name, guint oid_len, guint32 *subids) {
        g_assert(subids && *subids <= 2);
        if (oid_len) {
-               D(3,("\tOid (from subids): %s %s ",name?name:"NULL", oid_subid2string(subids,oid_len)));
+               gchar* sub = oid_subid2string(NULL, subids,oid_len);
+               D(3,("\tOid (from subids): %s %s ",name?name:"NULL", sub));
                add_oid(name,OID_KIND_UNKNOWN,NULL,NULL,oid_len,subids);
+               wmem_free(NULL, sub);
        } else {
                D(1,("Failed to add Oid: %s (from subids)",name?name:"NULL"));
        }
@@ -162,26 +181,34 @@ void oid_add(const char* name, guint oid_len, guint32 *subids) {
 
 void oid_add_from_string(const char* name, const gchar *oid_str) {
        guint32* subids;
-       guint oid_len = oid_string2subid(oid_str, &subids);
+       guint oid_len = oid_string2subid(NULL, oid_str, &subids);
 
        if (oid_len) {
-               D(3,("\tOid (from string): %s %s ",name?name:"NULL", oid_subid2string(subids,oid_len)));
+               gchar* sub = oid_subid2string(NULL, subids,oid_len);
+               D(3,("\tOid (from string): %s %s ",name?name:"NULL", sub));
                add_oid(name,OID_KIND_UNKNOWN,NULL,NULL,oid_len,subids);
+               wmem_free(NULL, sub);
        } else {
                D(1,("Failed to add Oid: %s %s ",name?name:"NULL", oid_str?oid_str:NULL));
        }
+       wmem_free(NULL, subids);
 }
 
 extern void oid_add_from_encoded(const char* name, const guint8 *oid, gint oid_len) {
-       guint32* subids;
-       guint subids_len = oid_encoded2subid(oid, oid_len, &subids);
+       guint32* subids = NULL;
+       guint subids_len = oid_encoded2subid(NULL, oid, oid_len, &subids);
 
        if (subids_len) {
-               D(3,("\tOid (from encoded): %s %s ",name, oid_subid2string(subids,subids_len)));
+               gchar* sub = oid_subid2string(NULL, subids,subids_len);
+               D(3,("\tOid (from encoded): %s %s ",name, sub));
                add_oid(name,OID_KIND_UNKNOWN,NULL,NULL,subids_len,subids);
+               wmem_free(NULL, sub);
        } else {
-               D(1,("Failed to add Oid: %s [%d]%s ",name?name:"NULL", oid_len,bytestring_to_str(oid, oid_len, ':')));
+               gchar* bytestr = bytestring_to_str(NULL, oid, oid_len, ':');
+               D(1,("Failed to add Oid: %s [%d]%s ",name?name:"NULL", oid_len, bytestr));
+               wmem_free(NULL, bytestr);
        }
+       wmem_free(NULL, subids);
 }
 
 #ifdef HAVE_LIBSMI
@@ -221,7 +248,7 @@ static uat_t* smi_modules_uat = NULL;
 
 static GString* smi_errors;
 
-UAT_CSTRING_CB_DEF(smi_mod,name,smi_module_t)
+UAT_DIRECTORYNAME_CB_DEF(smi_mod,name,smi_module_t)
 
 static void smi_error_handler(char *path, int line, int severity, char *msg, char *tag) {
                g_string_append_printf(smi_errors,"%s:%d %d %s %s\n",
@@ -232,9 +259,9 @@ static void smi_error_handler(char *path, int line, int severity, char *msg, cha
 }
 
 
-static void* smi_mod_copy_cb(void* dest, const void* orig, unsigned len _U_) {
-       const smi_module_t* m = orig;
-       smi_module_t* d = dest;
+static void* smi_mod_copy_cb(void* dest, const void* orig, size_t len _U_) {
+       const smi_module_t* m = (const smi_module_t*)orig;
+       smi_module_t* d = (smi_module_t*)dest;
 
        d->name = g_strdup(m->name);
 
@@ -242,7 +269,7 @@ static void* smi_mod_copy_cb(void* dest, const void* orig, unsigned len _U_) {
 }
 
 static void smi_mod_free_cb(void* p) {
-       smi_module_t* m = p;
+       smi_module_t* m = (smi_module_t*)p;
        g_free(m->name);
 }
 
@@ -254,7 +281,7 @@ static char* alnumerize(const char* name) {
        char c;
 
        for (;(c = *r); r++) {
-               if (isalnum(c) || c == '_' || c == '-' || c == '.') {
+               if (g_ascii_isalnum(c) || c == '_' || c == '-' || c == '.') {
                        *(w++) = c;
                } else if (c == ':' && r[1] == ':') {
                        *(w++) = '.';
@@ -275,7 +302,7 @@ static const oid_value_type_t* get_typedata(SmiType* smiType) {
         * SNMP Types and our FT_s
         */
        static const struct _type_mapping_t {
-               char* name;
+               const char* name;
                SmiBasetype base;
                const oid_value_type_t* type;
        } types[] =  {
@@ -289,7 +316,7 @@ static const oid_value_type_t* get_typedata(SmiType* smiType) {
                {"TimeStamp",SMI_BASETYPE_UNKNOWN,&timeticks_type},
                {"DisplayString",SMI_BASETYPE_UNKNOWN,&string_type},
                {"SnmpAdminString",SMI_BASETYPE_UNKNOWN,&string_type},
-               {"DateAndTime",SMI_BASETYPE_UNKNOWN,&string_type},
+               {"DateAndTime",SMI_BASETYPE_UNKNOWN,&date_and_time_type},
                {"Counter",SMI_BASETYPE_UNKNOWN,&counter32_type},
                {"Counter32",SMI_BASETYPE_UNKNOWN,&counter32_type},
                {"Unsigned32",SMI_BASETYPE_UNKNOWN,&unsigned32_type},
@@ -307,7 +334,7 @@ static const oid_value_type_t* get_typedata(SmiType* smiType) {
                {"enum",SMI_BASETYPE_ENUM,&integer_type},
                {"bits",SMI_BASETYPE_BITS,&bytes_type},
                {"unk",SMI_BASETYPE_UNKNOWN,&unknown_type},
-               {NULL,0,NULL}
+               {NULL,SMI_BASETYPE_UNKNOWN,NULL} /* SMI_BASETYPE_UNKNOWN = 0 */
        };
        const struct _type_mapping_t* t;
        SmiType* sT = smiType;
@@ -352,7 +379,7 @@ static guint get_non_implicit_size(SmiType* sT) {
                for (sR = smiGetFirstRange(sT); sR ; sR = smiGetNextRange(sR)) {
                        if (size == 0xffffffff) {
                                if (sR->minValue.value.unsigned32 == sR->maxValue.value.unsigned32) {
-                                       size = sR->minValue.value.unsigned32;
+                                       size = (guint32)sR->minValue.value.unsigned32;
                                } else {
                                        return 0;
                                }
@@ -406,7 +433,7 @@ static inline oid_kind_t smikind(SmiNode* sN, oid_key_t** key_p) {
 
                                typedata =  get_typedata(elType);
 
-                               k = g_malloc(sizeof(oid_key_t));
+                               k = g_new(oid_key_t,1);
 
                                oid1 = smiRenderOID(sN->oidlen, sN->oid, SMI_RENDER_QUALIFIED);
                                oid2 = smiRenderOID(elNode->oidlen, elNode->oid, SMI_RENDER_NAME);
@@ -486,67 +513,46 @@ static inline oid_kind_t smikind(SmiNode* sN, oid_key_t** key_p) {
                                                   || (ft == FT_INT8) || (ft == FT_INT16) || (ft == FT_INT24) || (ft == FT_INT32) \
                                                   || (ft == FT_UINT64) || (ft == FT_INT64) )
 
+static void unregister_mibs(void) {
+       /* TODO: Unregister "MIBs" proto and clean up field array and subtree array.
+        * Wireshark does not support that yet. :-( */
+
+       /* smiExit(); */
+}
+
+static void restart_needed_warning(void) {
+       if (oids_init_done)
+               report_failure("Wireshark needs to be restarted for these changes to take effect");
+}
+
 static void register_mibs(void) {
        SmiModule *smiModule;
        SmiNode *smiNode;
        guint i;
        int proto_mibs = -1;
-       GArray* hfa = g_array_new(FALSE,TRUE,sizeof(hf_register_info));
-       GArray* etta = g_array_new(FALSE,TRUE,sizeof(gint*));
-       static uat_field_t smi_fields[] = {
-               UAT_FLD_CSTRING(smi_mod,name,"Module name","The module's name"),
-               UAT_END_FIELDS
-       };
-       static uat_field_t smi_paths_fields[] = {
-               UAT_FLD_PATHNAME(smi_mod,name,"Directory path","The directory name"),
-               UAT_END_FIELDS
-       };
-       char* smi_load_error = NULL;
+       wmem_array_t* hfa;
+       GArray* etta;
        gchar* path_str;
 
-       smi_modules_uat = uat_new("SMI Modules",
-                                                         sizeof(smi_module_t),
-                                                         "smi_modules",
-                                                         FALSE,
-                                                         (void*)&smi_modules,
-                                                         &num_smi_modules,
-                                                         UAT_CAT_GENERAL,
-                                                         "ChSNMPSMIModules",
-                                                         smi_mod_copy_cb,
-                                                         NULL,
-                                                         smi_mod_free_cb,
-                                                         smi_fields);
-
-       smi_paths_uat = uat_new("SMI Paths",
-                                                         sizeof(smi_module_t),
-                                                         "smi_paths",
-                                                         FALSE,
-                                                         (void*)&smi_paths,
-                                                         &num_smi_paths,
-                                                         UAT_CAT_GENERAL,
-                                                         "ChSNMPSMIPaths",
-                                                         smi_mod_copy_cb,
-                                                         NULL,
-                                                         smi_mod_free_cb,
-                                                         smi_paths_fields);
-
-
-       smiInit(NULL);
-
-       uat_load(smi_modules_uat, &smi_load_error);
-
-       if (smi_load_error) {
-               report_failure("Error Loading SMI Modules Table: %s",smi_load_error);
+       if (!load_smi_modules) {
+               D(1,("OID resolution not enabled"));
                return;
        }
 
-       uat_load(smi_paths_uat, &smi_load_error);
-
-       if (smi_load_error) {
-               report_failure("Error Loading SMI Paths Table: %s",smi_load_error);
+       /* TODO: Remove this workaround when unregistration of "MIBs" proto is solved.
+        * Wireshark does not support that yet. :-( */
+       if (oids_init_done) {
+               D(1,("Exiting register_mibs() to avoid double registration of MIBs proto."));
                return;
+       } else {
+               oids_init_done = TRUE;
        }
 
+       hfa = wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info));
+       etta = g_array_new(FALSE,TRUE,sizeof(gint*));
+
+       smiInit(NULL);
+
        smi_errors = g_string_new("");
        smiSetErrorHandler(smi_error_handler);
 
@@ -563,15 +569,20 @@ static void register_mibs(void) {
                } else {
                        char* mod_name =  smiLoadModule(smi_modules[i].name);
                        if (mod_name)
-                               D(2,("Loaded: '%s'[%d] as %s",smi_modules[i].name,i,mod_name ));
+                               D(2,("Loaded: '%s'[%u] as %s",smi_modules[i].name,i,mod_name ));
                        else
-                               D(1,("Failed to load: '%s'[%d]",smi_modules[i].name,i));
+                               D(1,("Failed to load: '%s'[%u]",smi_modules[i].name,i));
                }
        }
 
        if (smi_errors->len) {
-               report_failure("The following errors were found while loading the MIBS:\n%s\n\n"
-                                          "The Current Path is: %s\n" , smi_errors->str , path_str);
+               if (!suppress_smi_errors) {
+                       report_failure("The following errors were found while loading the MIBS:\n%s\n\n"
+                                          "The Current Path is: %s\n\nYou can avoid this error message "
+                                          "by removing the missing MIB modules at Edit -> Preferences"
+                                          " -> Name Resolution -> SMI (MIB and PIB) modules or by "
+                                          "installing them.\n" , smi_errors->str , path_str);
+               }
                D(1,("Errors while loading:\n%s\n",smi_errors->str));
        }
 
@@ -584,6 +595,20 @@ static void register_mibs(void) {
 
                D(3,("\tModule: %s", smiModule->name));
 
+               /* TODO: Check libsmi version at compile time and disable this
+                * workaround for libsmi versions where this problem is fixed.
+                * Currently there is no such version. :-(
+                */
+               if (smiModule->conformance == 1) {
+                       if (!suppress_smi_errors) {
+                               report_failure("Stopped processing module %s due to "
+                                       "error(s) to prevent potential crash in libsmi.\n"
+                                       "Module's conformance level: %d.\n"
+                                       "See details at: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=560325\n",
+                                        smiModule->name, smiModule->conformance);
+                       }
+                       continue;
+               }
                for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
                         smiNode;
                         smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
@@ -592,6 +617,7 @@ static void register_mibs(void) {
                        const oid_value_type_t* typedata =  get_typedata(smiType);
                        oid_key_t* key;
                        oid_kind_t kind = smikind(smiNode,&key);
+                       char *sub;
                        char *oid = smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_QUALIFIED);
                        oid_info_t* oid_data = add_oid(oid,
                                                       kind,
@@ -601,20 +627,25 @@ static void register_mibs(void) {
                                                       smiNode->oid);
                        smi_free (oid);
 
+                       sub = oid_subid2string(NULL, smiNode->oid, smiNode->oidlen);
                        D(4,("\t\tNode: kind=%d oid=%s name=%s ",
-                                oid_data->kind, oid_subid2string(smiNode->oid, smiNode->oidlen), oid_data->name ));
+                                oid_data->kind, sub, oid_data->name));
+                       wmem_free(NULL, sub);
 
                        if ( typedata && oid_data->value_hfid == -2 ) {
                                SmiNamedNumber* smiEnum;
-                               hf_register_info hf = { &(oid_data->value_hfid), {
-                                       oid_data->name,
-                                       alnumerize(oid_data->name),
-                                       typedata->ft_type,
-                                       typedata->display,
-                                       NULL,
-                                       0,
-                                       smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_ALL),
-                                       HFILL }};
+                               hf_register_info hf;
+
+                               hf.p_id                     = &(oid_data->value_hfid);
+                               hf.hfinfo.name              = g_strdup(oid_data->name);
+                               hf.hfinfo.abbrev            = alnumerize(oid_data->name);
+                               hf.hfinfo.type              = typedata->ft_type;
+                               hf.hfinfo.display           = typedata->display;
+                               hf.hfinfo.strings           = NULL;
+                               hf.hfinfo.bitmask           = 0;
+                               hf.hfinfo.blurb             = smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_ALL);
+                               /* HFILL */
+                               HFILL_INIT(hf);
 
                                /* Don't allow duplicate blurb/name */
                                if (strcmp(hf.hfinfo.blurb, hf.hfinfo.name) == 0) {
@@ -629,12 +660,14 @@ static void register_mibs(void) {
 
                                        for(;smiEnum; smiEnum = smiGetNextNamedNumber(smiEnum)) {
                                                if (smiEnum->name) {
-                                                       value_string val = {smiEnum->value.value.integer32,g_strdup(smiEnum->name)};
+                                                       value_string val;
+                                                       val.value  = (guint32)smiEnum->value.value.integer32;
+                                                       val.strptr = g_strdup(smiEnum->name);
                                                        g_array_append_val(vals,val);
                                                }
                                        }
 
-                                       hf.hfinfo.strings = VALS(vals->data);
+                                       hf.hfinfo.strings = vals->data;
                                        g_array_free(vals,FALSE);
                                }
 #if 0 /* packet-snmp does not handle bits yet */
@@ -671,26 +704,29 @@ static void register_mibs(void) {
                                        g_array_append_val(hfa,hf2);
                                }
 #endif /* packet-snmp does not use this yet */
-                               g_array_append_val(hfa,hf);
+                               wmem_array_append_one(hfa,hf);
                        }
 
                        if ((key = oid_data->key)) {
                                for(; key; key = key->next) {
-                                       hf_register_info hf = { &(key->hfid), {
-                                               key->name,
-                                               alnumerize(key->name),
-                                               key->ft_type,
-                                               key->display,
-                                               NULL,
-                                               0,
-                                               NULL,
-                                               HFILL }};
-
-                                       D(5,("\t\t\tIndex: name=%s subids=%d key_type=%d",
+                                       hf_register_info hf;
+
+                                       hf.p_id                     = &(key->hfid);
+                                       hf.hfinfo.name              = key->name;
+                                       hf.hfinfo.abbrev            = alnumerize(key->name);
+                                       hf.hfinfo.type              = key->ft_type;
+                                       hf.hfinfo.display           = key->display;
+                                       hf.hfinfo.strings           = NULL;
+                                       hf.hfinfo.bitmask           = 0;
+                                       hf.hfinfo.blurb             = NULL;
+                                       /* HFILL */
+                                       HFILL_INIT(hf);
+
+                                       D(5,("\t\t\tIndex: name=%s subids=%u key_type=%d",
                                                 key->name, key->num_subids, key->key_type ));
 
                                        if (key->hfid == -2) {
-                                               g_array_append_val(hfa,hf);
+                                               wmem_array_append_one(hfa,hf);
                                                key->hfid = -1;
                                        } else {
                                                g_free((void*)hf.hfinfo.abbrev);
@@ -702,18 +738,109 @@ static void register_mibs(void) {
 
        proto_mibs = proto_register_protocol("MIBs", "MIBS", "mibs");
 
-       proto_register_field_array(proto_mibs, (hf_register_info*)hfa->data, hfa->len);
-
-       proto_register_subtree_array((gint**)etta->data, etta->len);
+       proto_register_field_array(proto_mibs, (hf_register_info*)wmem_array_get_raw(hfa), wmem_array_get_count(hfa));
 
+       proto_register_subtree_array((gint**)(void*)etta->data, etta->len);
 
        g_array_free(etta,TRUE);
-       g_array_free(hfa,FALSE);
 }
 #endif
 
+void oid_pref_init(module_t *nameres)
+{
+#ifdef HAVE_LIBSMI
+       static uat_field_t smi_fields[] = {
+               UAT_FLD_CSTRING(smi_mod,name,"Module name","The module's name"),
+               UAT_END_FIELDS
+       };
+       static uat_field_t smi_paths_fields[] = {
+               UAT_FLD_DIRECTORYNAME(smi_mod,name,"Directory path","The directory name"),
+               UAT_END_FIELDS
+       };
+
+    prefs_register_bool_preference(nameres, "load_smi_modules",
+                                  "Enable OID resolution",
+                                  "You must restart Wireshark for this change to take effect",
+                                  &load_smi_modules);
+
+    prefs_register_bool_preference(nameres, "suppress_smi_errors",
+                                  "Suppress SMI errors",
+                                  "Some errors can be ignored. If unsure, set to false.",
+                                  &suppress_smi_errors);
+
+    smi_paths_uat = uat_new("SMI Paths",
+                            sizeof(smi_module_t),
+                            "smi_paths",
+                            FALSE,
+                            (void**)&smi_paths,
+                            &num_smi_paths,
+    /* affects dissection of packets (as the MIBs and PIBs affect the
+       interpretation of e.g. SNMP variable bindings), but not set of
+       named fields
+
+       XXX - if named fields are generated from the MIBs and PIBs
+       for particular variable bindings, this *does* affect the set
+       of named fields! */
+                            UAT_AFFECTS_DISSECTION,
+                            "ChSNMPSMIPaths",
+                            smi_mod_copy_cb,
+                            NULL,
+                            smi_mod_free_cb,
+                            restart_needed_warning,
+                            smi_paths_fields);
+
+    prefs_register_uat_preference(nameres,
+                                  "smi_paths",
+                                  "SMI (MIB and PIB) paths",
+                                  "Search paths for SMI (MIB and PIB) modules. You must\n"
+                                  "restart Wireshark for these changes to take effect.",
+                                  smi_paths_uat);
+
+    smi_modules_uat = uat_new("SMI Modules",
+                              sizeof(smi_module_t),
+                              "smi_modules",
+                              FALSE,
+                              (void**)&smi_modules,
+                              &num_smi_modules,
+    /* affects dissection of packets (as the MIBs and PIBs affect the
+       interpretation of e.g. SNMP variable bindings), but not set of
+       named fields
+
+       XXX - if named fields are generated from the MIBs and PIBs
+       for particular variable bindings, would this affect the set
+       of named fields? */
+                              UAT_AFFECTS_DISSECTION,
+                              "ChSNMPSMIModules",
+                              smi_mod_copy_cb,
+                              NULL,
+                              smi_mod_free_cb,
+                              restart_needed_warning,
+                              smi_fields);
+
+    prefs_register_uat_preference(nameres,
+                                  "smi_modules",
+                                  "SMI (MIB and PIB) modules",
+                                  "List of enabled SMI (MIB and PIB) modules. You must\n"
+                                  "restart Wireshark for these changes to take effect.",
+                                  smi_modules_uat);
+
+#else
+    prefs_register_static_text_preference(nameres, "load_smi_modules_static",
+                            "Enable OID resolution: N/A",
+                            "Support for OID resolution was not compiled into this version of Wireshark");
+
+    prefs_register_static_text_preference(nameres, "suppress_smi_errors_static",
+                            "Suppress SMI errors: N/A",
+                            "Support for OID resolution was not compiled into this version of Wireshark");
+
+    prefs_register_static_text_preference(nameres, "smi_module_path",
+                            "SMI (MIB and PIB) modules and paths: N/A",
+                            "Support for OID resolution was not compiled into this version of Wireshark");
+#endif
+}
 
 void oids_init(void) {
+       prepopulate_oids();
 #ifdef HAVE_LIBSMI
        register_mibs();
 #else
@@ -721,12 +848,28 @@ void oids_init(void) {
 #endif
 }
 
-const char* oid_subid2string(guint32* subids, guint len) {
-       char* s = ep_alloc0(((len)*11)+1);
-       char* w = s;
+void oids_cleanup(void) {
+#ifdef HAVE_LIBSMI
+       unregister_mibs();
+#else
+       D(1,("libsmi disabled oid resolution not enabled"));
+#endif
+}
+
+char* oid_subid2string(wmem_allocator_t *scope, guint32* subids, guint len) {
+       return rel_oid_subid2string(scope, subids, len, TRUE);
+}
+char* rel_oid_subid2string(wmem_allocator_t *scope, guint32* subids, guint len, gboolean is_absolute) {
+       char *s, *w;
+
+       if(!subids || len == 0)
+               return wmem_strdup(scope, "*** Empty OID ***");
+
+       s = (char *)wmem_alloc0(scope, ((len)*11)+2);
+       w = s;
 
-       if(!subids)
-               return "*** Empty OID ***";
+       if (!is_absolute)
+               *w++ = '.';
 
        do {
                w += g_snprintf(w,12,"%u.",*subids++);
@@ -737,37 +880,33 @@ const char* oid_subid2string(guint32* subids, guint len) {
        return s;
 }
 
-guint check_num_oid(const char* str) {
+static guint check_num_oid(const char* str) {
        const char* r = str;
-       char c = '\0';
+       char c = '.';
        guint n = 0;
 
        D(8,("check_num_oid: '%s'",str));
-       if (*r == '.' || *r == '\0') return 0;
+       if (!r) return 0;
 
        do {
-               D(9,("\tcheck_num_oid: '%c' %d",*r,n));
+               D(9,("\tcheck_num_oid: '%c' %u",*r,n));
                switch(*r) {
-                       case '.':
+                       case '.': case '\0':
                                n++;
                                if (c == '.') return 0;
+                               break;
                        case '1' : case '2' : case '3' : case '4' : case '5' :
                        case '6' : case '7' : case '8' : case '9' : case '0' :
                                continue;
-                       case '\0':
-                               n++;
-                               break;
                        default:
                                return 0;
                }
        } while((c = *r++));
 
-       if (c == '.') return 0;
-
        return n;
 }
 
-guint oid_string2subid(const char* str, guint32** subids_p) {
+guint oid_string2subid(wmem_allocator_t *scope, const char* str, guint32** subids_p) {
        const char* r = str;
        guint32* subids;
        guint32* subids_overflow;
@@ -785,7 +924,7 @@ guint oid_string2subid(const char* str, guint32** subids_p) {
                return 0;
        }
 
-       *subids_p = subids = ep_alloc0(sizeof(guint32)*n);
+       *subids_p = subids = wmem_alloc0_array(scope, guint32, n);
        subids_overflow = subids + n;
        do switch(*r) {
                case '.':
@@ -815,10 +954,13 @@ guint oid_string2subid(const char* str, guint32** subids_p) {
 }
 
 
-guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_p) {
+guint oid_encoded2subid(wmem_allocator_t *scope, const guint8 *oid_bytes, gint oid_len, guint32** subids_p) {
+       return oid_encoded2subid_sub(scope, oid_bytes, oid_len, subids_p, TRUE);
+}
+guint oid_encoded2subid_sub(wmem_allocator_t *scope, const guint8 *oid_bytes, gint oid_len, guint32** subids_p,
+               gboolean is_first) {
        gint i;
-       guint n = 1;
-       gboolean is_first = TRUE;
+       guint n = is_first ? 1 : 0;
        guint32* subids;
        guint32* subid_overflow;
        /*
@@ -829,9 +971,22 @@ guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_
 
        for (i=0; i<oid_len; i++) { if (! (oid_bytes[i] & 0x80 )) n++; }
 
-       *subids_p = subids = ep_alloc(sizeof(guint32)*n);
+       *subids_p = subids = (guint32 *)wmem_alloc(scope, sizeof(guint32)*n);
        subid_overflow = subids+n;
 
+       /* If n is 0 or 1 (depending on how it was initialized) then we found
+        * no bytes in the OID with first bit cleared, so initialize our one
+        * byte (if any) to zero and return. This *seems* to be the right thing
+        * to do in this situation, and at the very least it avoids
+        * uninitialized memory errors that would otherwise occur. */
+       if (is_first && n == 1) {
+               *subids = 0;
+               return n;
+       }
+       else if (!is_first && n == 0) {
+               return n;
+       }
+
        for (i=0; i<oid_len; i++){
                guint8 byte = oid_bytes[i];
 
@@ -854,7 +1009,10 @@ guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_
                }
 
                if( subids >= subid_overflow || subid > 0xffffffff) {
-                       *subids_p=NULL;
+                       /* scope may be NULL in which case we must free our
+                        * useless buffer before returning */
+                       wmem_free(scope, *subids_p);
+                       *subids_p = NULL;
                        return 0;
                }
 
@@ -862,6 +1020,8 @@ guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_
                subid = 0;
        }
 
+       g_assert(subids == subid_overflow);
+
        return n;
 }
 
@@ -876,7 +1036,7 @@ oid_info_t* oid_get(guint len, guint32* subids, guint* matched, guint* left) {
        }
 
        for( i=0; i < len; i++) {
-               oid_info_t* next_oid = emem_tree_lookup32(curr_oid->children,subids[i]);
+               oid_info_t* next_oid = (oid_info_t *)wmem_tree_lookup32(curr_oid->children,subids[i]);
                if (next_oid) {
                        curr_oid = next_oid;
                } else {
@@ -890,39 +1050,50 @@ done:
 }
 
 
-oid_info_t* oid_get_from_encoded(const guint8 *bytes, gint byteslen, guint32** subids_p, guint* matched_p, guint* left_p) {
-       guint subids_len = oid_encoded2subid(bytes, byteslen, subids_p);
+oid_info_t* oid_get_from_encoded(wmem_allocator_t *scope, const guint8 *bytes, gint byteslen, guint32** subids_p, guint* matched_p, guint* left_p) {
+       guint subids_len = oid_encoded2subid(scope, bytes, byteslen, subids_p);
        return oid_get(subids_len, *subids_p, matched_p, left_p);
 }
 
-oid_info_t* oid_get_from_string(const gchar *oid_str, guint32** subids_p, guint* matched, guint* left) {
-       guint subids_len = oid_string2subid(oid_str, subids_p);
+oid_info_t* oid_get_from_string(wmem_allocator_t *scope, const gchar *oid_str, guint32** subids_p, guint* matched, guint* left) {
+       guint subids_len = oid_string2subid(scope, oid_str, subids_p);
        return oid_get(subids_len, *subids_p, matched, left);
 }
 
-const gchar *oid_resolved_from_encoded(const guint8 *oid, gint oid_len) {
-       guint32 *subid_oid;
-       guint subid_oid_length = oid_encoded2subid(oid, oid_len, &subid_oid);
+gchar *oid_resolved_from_encoded(wmem_allocator_t *scope, const guint8 *oid, gint oid_len) {
+       guint32 *subid_oid = NULL;
+       gchar * ret;
+       guint subid_oid_length = oid_encoded2subid(NULL, oid, oid_len, &subid_oid);
+
+       ret = oid_resolved(scope, subid_oid_length, subid_oid);
+       wmem_free(NULL, subid_oid);
+       return ret;
+}
+
+gchar *rel_oid_resolved_from_encoded(wmem_allocator_t *scope, const guint8 *oid, gint oid_len) {
+       guint32 *subid_oid = NULL;
+       gchar* ret;
+       guint subid_oid_length = oid_encoded2subid_sub(NULL, oid, oid_len, &subid_oid, FALSE);
 
-       return oid_resolved(subid_oid_length, subid_oid);
+       ret = rel_oid_subid2string(scope, subid_oid, subid_oid_length, FALSE);
+       wmem_free(NULL, subid_oid);
+       return ret;
 }
 
 
-guint oid_subid2encoded(guint subids_len, guint32* subids, guint8** bytes_p) {
+guint oid_subid2encoded(wmem_allocator_t *scope, guint subids_len, guint32* subids, guint8** bytes_p) {
        guint bytelen = 0;
        guint i;
        guint32 subid;
        guint8* b;
 
-       if ( !subids || subids_len <= 0) {
+       if ( !subids || subids_len <= 1) {
                *bytes_p = NULL;
                return 0;
        }
 
-       subid = (subids[0] * 40) + subids[1];
-       i = 2;
-
-       do {
+       for (subid=subids[0] * 40, i = 1; i<subids_len; i++, subid=0) {
+               subid += subids[i];
                if (subid <= 0x0000007F) {
                        bytelen += 1;
                } else if (subid <= 0x00003FFF ) {
@@ -934,18 +1105,14 @@ guint oid_subid2encoded(guint subids_len, guint32* subids, guint8** bytes_p) {
                } else {
                        bytelen += 5;
                }
+       }
 
-                       subid = subids[i];
-       } while ( i++ < subids_len );
-
-       *bytes_p = b = ep_alloc(bytelen);
-
-       subid = (subids[0] * 40) + subids[1];
-       i = 2;
+       *bytes_p = b = (guint8 *)wmem_alloc(scope, bytelen);
 
-       do {
+       for (subid=subids[0] * 40, i = 1; i<subids_len; i++, subid=0) {
                guint len;
 
+               subid += subids[i];
                if ((subid <= 0x0000007F )) len = 1;
                else if ((subid <= 0x00003FFF )) len = 2;
                else if ((subid <= 0x001FFFFF )) len = 3;
@@ -954,104 +1121,127 @@ guint oid_subid2encoded(guint subids_len, guint32* subids, guint8** bytes_p) {
 
                switch(len) {
                        default: *bytes_p=NULL; return 0;
-                       case 5: *(b++) = ((subid & 0xF0000000) << 28) | 0x80;
-                       case 4: *(b++) = ((subid & 0x0FE00000 ) >> 21)  | 0x80;
-                       case 3: *(b++) = ((subid & 0x001FC000 ) >> 14)  | 0x80;
-                       case 2: *(b++) = ((subid & 0x00003F10 ) >> 7)  | 0x80;
-                       case 1: *(b++) =  subid & 0x0000007F ; break;
+                       case 5: *(b++) = ((subid & 0xF0000000) >> 28) | 0x80;
+                       case 4: *(b++) = ((subid & 0x0FE00000) >> 21) | 0x80;
+                       case 3: *(b++) = ((subid & 0x001FC000) >> 14) | 0x80;
+                       case 2: *(b++) = ((subid & 0x00003F80) >> 7)  | 0x80;
+                       case 1: *(b++) =   subid & 0x0000007F ; break;
                }
-
-               subid = subids[i];
-       } while ( i++ < subids_len);
+       }
 
        return bytelen;
 }
 
-const gchar* oid_encoded2string(const guint8* encoded, guint len) {
-       guint32* subids;
-       guint subids_len = oid_encoded2subid(encoded, len, &subids);
+gchar* oid_encoded2string(wmem_allocator_t *scope, const guint8* encoded, guint len) {
+       guint32* subids = NULL;
+       gchar* ret;
+       guint subids_len = oid_encoded2subid(NULL, encoded, len, &subids);
 
        if (subids_len) {
-               return oid_subid2string(subids,subids_len);
+               ret = oid_subid2string(scope, subids,subids_len);
        } else {
-               return "";
+               ret = wmem_strdup(scope, "");
        }
+
+       wmem_free(NULL, subids);
+       return ret;
 }
 
+gchar* rel_oid_encoded2string(wmem_allocator_t *scope, const guint8* encoded, guint len) {
+       guint32* subids = NULL;
+       gchar* ret;
+       guint subids_len = oid_encoded2subid_sub(NULL, encoded, len, &subids, FALSE);
+
+       if (subids_len) {
+               ret = rel_oid_subid2string(scope, subids,subids_len, FALSE);
+       } else {
+               ret = wmem_strdup(scope, "");
+       }
 
+       wmem_free(NULL, subids);
+       return ret;
+}
 
-guint oid_string2encoded(const char *oid_str, guint8 **bytes) {
+guint oid_string2encoded(wmem_allocator_t *scope, const char *oid_str, guint8 **bytes) {
        guint32* subids;
        guint32 subids_len;
        guint byteslen;
 
-               if ( ( subids_len = oid_string2subid(oid_str, &subids) )
-                        &&
-                        ( byteslen = oid_subid2encoded(subids_len, subids, bytes) )  ) {
-                       return byteslen;
-               }
+       if ( (subids_len = oid_string2subid(NULL, oid_str, &subids)) &&
+            (byteslen   = oid_subid2encoded(scope, subids_len, subids, bytes)) ) {
+               wmem_free(NULL, subids);
+               return byteslen;
+       }
+       wmem_free(NULL, subids);
        return 0;
 }
 
-char* oid2str(oid_info_t* oid, guint32* subids, guint len, guint left) {
-       if (left == 0) {
-               return oid->name;
-       } else {
-               return ep_strdup_printf("%s.%s",oid->name,oid_subid2string(subids+(len-left),left));
-       }
-}
+gchar *oid_resolved_from_string(wmem_allocator_t *scope, const gchar *oid_str) {
+       guint32     *subid_oid;
+       guint        subid_oid_length;
+       gchar *resolved;
 
-const gchar *oid_resolved_from_string(const gchar *oid_str) {
-       guint32 *subid_oid;
-       guint subid_oid_length = oid_string2subid(oid_str, &subid_oid);
+       subid_oid_length = oid_string2subid(NULL, oid_str, &subid_oid);
+       resolved         = oid_resolved(scope, subid_oid_length, subid_oid);
 
-       return oid_resolved(subid_oid_length, subid_oid);
+       wmem_free(NULL, subid_oid);
+
+       return resolved;
 }
 
-const gchar *oid_resolved(guint32 num_subids, guint32* subids) {
+gchar *oid_resolved(wmem_allocator_t *scope, guint32 num_subids, guint32* subids) {
        guint matched;
        guint left;
        oid_info_t* oid;
 
        if(! (subids && *subids <= 2 ))
-               return "*** Malformed OID ***";
+               return wmem_strdup(scope, "*** Malformed OID ***");
 
        oid = oid_get(num_subids, subids, &matched, &left);
 
        while (! oid->name ) {
                if (!(oid = oid->parent)) {
-                       return oid_subid2string(subids,num_subids);
+                       return oid_subid2string(scope, subids,num_subids);
                }
                left++;
                matched--;
        }
 
        if (left) {
-               return ep_strdup_printf("%s.%s",
-                                       oid->name ? oid->name : oid_subid2string(subids,matched),
-                                       oid_subid2string(&(subids[matched]),left));
+               gchar *ret,
+                         *str1 = oid_subid2string(NULL, subids,matched),
+                         *str2 = oid_subid2string(NULL, &(subids[matched]),left);
+
+               ret = wmem_strdup_printf(scope, "%s.%s", oid->name ? oid->name : str1, str2);
+               wmem_free(NULL, str1);
+               wmem_free(NULL, str2);
+               return ret;
        } else {
-               return oid->name ? oid->name : oid_subid2string(subids,matched);
+               return oid->name ? wmem_strdup(scope, oid->name) : oid_subid2string(scope, subids,matched);
        }
 }
 
-extern void oid_both(guint oid_len, guint32 *subids, char** resolved_p, char** numeric_p) {
-       *resolved_p = (void*)oid_resolved(oid_len,subids);
-       *numeric_p = (void*)oid_subid2string(subids,oid_len);
+extern void oid_both(wmem_allocator_t *scope, guint oid_len, guint32 *subids, gchar** resolved_p, gchar** numeric_p) {
+       *resolved_p = oid_resolved(scope, oid_len,subids);
+       *numeric_p = oid_subid2string(scope, subids,oid_len);
 }
 
-extern void oid_both_from_encoded(const guint8 *oid, gint oid_len, char** resolved_p, char** numeric_p) {
-       guint32* subids;
-       guint subids_len = oid_encoded2subid(oid, oid_len, &subids);
-       *resolved_p = (void*)oid_resolved(subids_len,subids);
-       *numeric_p = (void*)oid_subid2string(subids,subids_len);
+extern void oid_both_from_encoded(wmem_allocator_t *scope, const guint8 *oid, gint oid_len, gchar** resolved_p, gchar** numeric_p) {
+       guint32* subids = NULL;
+       guint subids_len = oid_encoded2subid(NULL, oid, oid_len, &subids);
+       *resolved_p = oid_resolved(scope, subids_len,subids);
+       *numeric_p = oid_subid2string(scope, subids,subids_len);
+       wmem_free(NULL, subids);
 }
 
-extern void oid_both_from_string(const gchar *oid_str, char** resolved_p, char** numeric_p) {
-       guint32* subids;
-       guint subids_len = oid_string2subid(oid_str, &subids);
-       *resolved_p = (void*)oid_resolved(subids_len,subids);
-       *numeric_p = (void*)oid_subid2string(subids,subids_len);
+void oid_both_from_string(wmem_allocator_t *scope, const gchar *oid_str, gchar** resolved_p, gchar** numeric_p) {
+       guint32 *subids;
+       guint    subids_len;
+
+       subids_len  = oid_string2subid(NULL, oid_str, &subids);
+       *resolved_p = oid_resolved(scope, subids_len,subids);
+       *numeric_p  = oid_subid2string(scope, subids,subids_len);
+       wmem_free(NULL, subids);
 }
 
 /**
@@ -1061,31 +1251,33 @@ extern gchar *
 oid_get_default_mib_path(void) {
 #ifdef HAVE_LIBSMI
        GString* path_str;
-       gchar *path_ret;
        char *path;
        guint i;
 
        path_str = g_string_new("");
+
+       if (!load_smi_modules) {
+               D(1,("OID resolution not enabled"));
+               return path_str->str;
+       }
 #ifdef _WIN32
 #define PATH_SEPARATOR ";"
        path = get_datafile_path("snmp\\mibs");
        g_string_append_printf(path_str, "%s;", path);
        g_free (path);
 
-       path = get_persconffile_path("snmp\\mibs", FALSE, FALSE);
+       path = get_persconffile_path("snmp\\mibs", FALSE);
        g_string_append_printf(path_str, "%s", path);
        g_free (path);
 #else
 #define PATH_SEPARATOR ":"
        path = smiGetPath();
-#ifdef __APPLE__
        g_string_append(path_str, "/usr/share/snmp/mibs");
        if (strlen(path) > 0 ) {
                g_string_append(path_str, PATH_SEPARATOR);
        }
-#endif
        g_string_append_printf(path_str, "%s", path);
-       free (path);
+       smi_free(path);
 #endif
 
        for(i=0;i<num_smi_paths;i++) {
@@ -1095,9 +1287,7 @@ oid_get_default_mib_path(void) {
                g_string_append_printf(path_str,PATH_SEPARATOR "%s",smi_paths[i].name);
        }
 
-       path_ret = path_str->str;
-       g_string_free(path_str, FALSE);
-       return path_ret;
+       return g_string_free(path_str, FALSE);
 #else /* HAVE_LIBSMI */
         return g_strdup("");
 #endif
@@ -1105,18 +1295,19 @@ oid_get_default_mib_path(void) {
 
 #ifdef DEBUG_OIDS
 char* oid_test_a2b(guint32 num_subids, guint32* subids) {
-       guint8* sub2enc;
-       guint8* str2enc;
-       guint32* enc2sub;
+       guint8* sub2enc = NULL;
+       guint8* str2enc = NULL;
+       guint32* enc2sub = NULL;
        guint32* str2sub;
-       const char* sub2str = oid_subid2string(subids, num_subids);
-       guint sub2enc_len = oid_subid2encoded(num_subids, subids,&sub2enc);
-       guint enc2sub_len = oid_encoded2subid(sub2enc, sub2enc_len, &enc2sub);
-       const char* enc2str = oid_encoded2string(sub2enc, sub2enc_len);
-       guint str2enc_len = oid_string2encoded(sub2str,&str2enc);
+       char* ret;
+       char* sub2str = oid_subid2string(NULL, subids, num_subids);
+       guint sub2enc_len = oid_subid2encoded(NULL, num_subids, subids,&sub2enc);
+       guint enc2sub_len = oid_encoded2subid(NULL, sub2enc, sub2enc_len, &enc2sub);
+       char* enc2str = oid_encoded2string(NULL, sub2enc, sub2enc_len);
+       guint str2enc_len = oid_string2encoded(NULL, sub2str,&str2enc);
        guint str2sub_len = oid_string2subid(sub2str,&str2sub);
 
-       return ep_strdup_printf(
+       ret = wmem_strdup_printf(wmem_packet_scope(),
                                                        "oid_subid2string=%s \n"
                                                        "oid_subid2encoded=[%d]%s \n"
                                                        "oid_encoded2subid=%s \n "
@@ -1124,12 +1315,19 @@ char* oid_test_a2b(guint32 num_subids, guint32* subids) {
                                                        "oid_string2encoded=[%d]%s \n"
                                                        "oid_string2subid=%s \n "
                                                        ,sub2str
-                                                       ,sub2enc_len,bytestring_to_str(sub2enc, sub2enc_len, ':')
-                                                       ,enc2sub ? oid_subid2string(enc2sub,enc2sub_len) : "-"
+                                                       ,sub2enc_len,bytestring_to_str(wmem_packet_scope(), sub2enc, sub2enc_len, ':')
+                                                       ,enc2sub ? oid_subid2string(wmem_packet_scope(), enc2sub,enc2sub_len) : "-"
                                                        ,enc2str
-                                                       ,str2enc_len,bytestring_to_str(str2enc, str2enc_len, ':')
-                                                       ,str2sub ? oid_subid2string(str2sub,str2sub_len) : "-"
+                                                       ,str2enc_len,bytestring_to_str(wmem_packet_scope(), str2enc, str2enc_len, ':')
+                                                       ,str2sub ? oid_subid2string(wmem_packet_scope(), str2sub,str2sub_len) : "-"
                                                        );
+
+       wmem_free(NULL, sub2str);
+       wmem_free(NULL, enc2sub);
+       wmem_free(NULL, sub2enc);
+       wmem_free(NULL, str2enc);
+       wmem_free(NULL, enc2str);
+       return ret;
 }
 
 void add_oid_debug_subtree(oid_info_t* oid_info, proto_tree *tree) {
@@ -1137,7 +1335,7 @@ void add_oid_debug_subtree(oid_info_t* oid_info, proto_tree *tree) {
        static const char* key_types[] = {"OID_KEY_TYPE_WRONG","OID_KEY_TYPE_INTEGER",
                                                                                "OID_KEY_TYPE_FIXED_STRING","OID_KEY_TYPE_FIXED_BYTES","OID_KEY_TYPE_STRING",
                                                                                "OID_KEY_TYPE_BYTES","OID_KEY_TYPE_NSAP","OID_KEY_TYPE_OID","OID_KEY_TYPE_IPADDR"};
-       proto_item* pi = proto_tree_add_text(tree,NULL,0,0,
+       proto_item* pi = proto_tree_add_debug_text(tree,NULL,0,0,
        "OidInfo: Name='%s' sub-id=%u  kind=%s  hfid=%d",
        oid_info->name ? oid_info->name : "",
        oid_info->subid,
@@ -1147,7 +1345,7 @@ void add_oid_debug_subtree(oid_info_t* oid_info, proto_tree *tree) {
        oid_key_t* key;
 
        for(key = oid_info->key; key; key = key->next) {
-               proto_tree_add_text(pt,NULL,0,0,
+               proto_tree_add_debug_text(pt,NULL,0,0,
                "Key: name='%s' num_subids=%d type=%s",
                key->name,
                key->key_type <= OID_KEY_TYPE_IPADDR ? key_types[key->key_type] : "BROKEN"
@@ -1155,7 +1353,7 @@ void add_oid_debug_subtree(oid_info_t* oid_info, proto_tree *tree) {
        };
 
        if (oid_info->parent) {
-               pi = proto_tree_add_text(pt,NULL,0,0,"Parent:");
+               pi = proto_tree_add_debug_text(pt,NULL,0,0,"Parent:");
                pt = proto_item_add_subtree(pi,0);
                add_oid_debug_subtree(oid_info->parent, pt);
        }
@@ -1171,7 +1369,6 @@ void add_oid_debug_subtree(oid_info_t* oid_info, proto_tree *tree) {
  * indent-tabs-mode: t
  * End:
  *
- * ex: set shiftwidth=8 tabstop=8 noexpandtab
+ * ex: set shiftwidth=8 tabstop=8 noexpandtab:
  * :indentSize=8:tabSize=8:noTabs=false:
  */
-