Constify.
[obnox/wireshark/wip.git] / epan / oids.c
index 5251faa8804a8c193bcbbd346f16c671dee05407..153a585ab188725738de528d4251074cc610d22f 100644 (file)
@@ -1,7 +1,7 @@
 /* oids.c
  * Object IDentifier Support
  *
- * (c) 2007, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
  *
  * $Id$
  *
@@ -56,16 +56,21 @@ static const oid_value_type_t integer_type =    { FT_INT32,  BASE_DEC,  BER_CLAS
 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_UINT32, BASE_DEC,  BER_CLASS_APP, 1,                       1,   4, OID_KEY_TYPE_INTEGER, 1};
+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};
+/*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 timeticks_type =  { FT_UINT64, BASE_DEC,  BER_CLASS_APP, 3,                       1,   5, OID_KEY_TYPE_INTEGER, 1};
 static const oid_value_type_t opaque_type =     { FT_BYTES,  BASE_NONE, BER_CLASS_APP, 4,                       1,   4, OID_KEY_TYPE_BYTES,   0};
 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};
 static const oid_value_type_t float_type =      { FT_FLOAT,  BASE_DEC,  BER_CLASS_UNI, BER_UNI_TAG_OCTETSTRING, 4,   4, OID_KEY_TYPE_WRONG,   0};
 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_BYTES,   6};
+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 unknown_type =    { FT_BYTES,  BASE_NONE, BER_CLASS_ANY, BER_TAG_ANY,             0,  -1, OID_KEY_TYPE_WRONG,   0};
 
@@ -180,6 +185,28 @@ extern void oid_add_from_encoded(const char* name, const guint8 *oid, gint oid_l
 }
 
 #ifdef HAVE_LIBSMI
+/* de-allocate storage mallocated by libsmi                            */
+/*                                                                     */
+/* XXX: libsmi provides access to smiFree as of libsmi v 0.4.8.        */
+/*      On Windows: Wireshark 1.01 and later is built and distributed  */
+/*      with libsmi 0.4.8 (or newer).                                  */
+/*      On non-Windows systems, free() should be OK for libsmi         */
+/*       versions older than 0.4.8.                                    */
+
+static void smi_free(void *ptr) {
+
+#if (SMI_VERSION_MAJOR >= 0) && (SMI_VERSION_MINOR >= 4) && (SMI_VERSION_PATCHLEVEL >= 8)
+       smiFree(ptr);
+#else
+ #ifdef _WIN32
+ #error Invalid Windows libsmi version ?? !!
+ #endif
+#define xx_free free  /* hack so checkAPIs.pl doesn't complain */
+       xx_free(ptr);
+#endif
+}
+
+
 typedef struct smi_module_t {
        char* name;
 } smi_module_t;
@@ -197,7 +224,7 @@ static GString* smi_errors;
 UAT_CSTRING_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_sprintfa(smi_errors,"%s:%d %d %s %s\n",
+               g_string_append_printf(smi_errors,"%s:%d %d %s %s\n",
                                                  path ? path : "-",
                                                  line, severity,
                                                  tag ? tag : "-",
@@ -216,7 +243,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;
-       if (m->name) g_free(m->name);
+       g_free(m->name);
 }
 
 
@@ -239,7 +266,7 @@ static char* alnumerize(const char* name) {
        return s;
 }
 
-const oid_value_type_t* get_typedata(SmiType* smiType) {
+static const oid_value_type_t* get_typedata(SmiType* smiType) {
        /*
         * There has to be a better way to know if a given
         * OCTETSTRING type is actually human readable text,
@@ -259,7 +286,7 @@ const oid_value_type_t* get_typedata(SmiType* smiType) {
                {"MacAddress",SMI_BASETYPE_UNKNOWN,&ether_type},
                {"TimeTicks",SMI_BASETYPE_UNKNOWN,&timeticks_type},
                {"Ipv6Address",SMI_BASETYPE_UNKNOWN,&ipv6_type},
-               {"TimeStamp",SMI_BASETYPE_UNKNOWN,&integer_type},
+               {"TimeStamp",SMI_BASETYPE_UNKNOWN,&timeticks_type},
                {"DisplayString",SMI_BASETYPE_UNKNOWN,&string_type},
                {"SnmpAdminString",SMI_BASETYPE_UNKNOWN,&string_type},
                {"DateAndTime",SMI_BASETYPE_UNKNOWN,&string_type},
@@ -291,16 +318,12 @@ const oid_value_type_t* get_typedata(SmiType* smiType) {
                for (t = types; t->type ; t++ ) {
                        char* name = smiRenderType(sT, SMI_RENDER_NAME);
                        if (name && t->name && g_str_equal(name, t->name )) {
-#ifndef WIN32
-                               free (name);
-#endif
+                               smi_free(name);
                                return t->type;
                        }
-#ifndef WIN32
                        if (name) {
-                               free (name);
+                               smi_free (name);
                        }
-#endif
                }
        } while(( sT  = smiGetParentType(sT) ));
 
@@ -388,10 +411,8 @@ static inline oid_kind_t smikind(SmiNode* sN, oid_key_t** key_p) {
                                oid1 = smiRenderOID(sN->oidlen, sN->oid, SMI_RENDER_QUALIFIED);
                                oid2 = smiRenderOID(elNode->oidlen, elNode->oid, SMI_RENDER_NAME);
                                k->name = g_strdup_printf("%s.%s", oid1, oid2);
-#ifndef WIN32
-                               free (oid1);
-                               free (oid2);
-#endif
+                               smi_free (oid1);
+                               smi_free (oid2);
 
                                k->hfid = -2;
                                k->ft_type = typedata ? typedata->ft_type : FT_BYTES;
@@ -438,7 +459,7 @@ static inline oid_kind_t smikind(SmiNode* sN, oid_key_t** key_p) {
                                kl = k;
                        }
 
-                       if (implied) {
+                       if (implied && kl) {
                                switch (kl->key_type) {
                                        case OID_KEY_TYPE_BYTES:  kl->key_type = OID_KEY_TYPE_IMPLIED_BYTES; break;
                                        case OID_KEY_TYPE_STRING: kl->key_type = OID_KEY_TYPE_IMPLIED_STRING; break;
@@ -465,7 +486,7 @@ 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) )
 
-void register_mibs(void) {
+static void register_mibs(void) {
        SmiModule *smiModule;
        SmiNode *smiNode;
        guint i;
@@ -473,11 +494,11 @@ void register_mibs(void) {
        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,"The module's name"),
+               UAT_FLD_CSTRING(smi_mod,name,"Module name","The module's name"),
                UAT_END_FIELDS
        };
        static uat_field_t smi_paths_fields[] = {
-               UAT_FLD_CSTRING(smi_mod,name,"The directory name"),
+               UAT_FLD_PATHNAME(smi_mod,name,"Directory path","The directory name"),
                UAT_END_FIELDS
        };
        char* smi_load_error = NULL;
@@ -526,20 +547,17 @@ void register_mibs(void) {
                return;
        }
 
+       smi_errors = g_string_new("");
+       smiSetErrorHandler(smi_error_handler);
+
        path_str = oid_get_default_mib_path();
        D(1,("SMI Path: '%s'",path_str));
 
        smiSetPath(path_str);
 
-
-
-       smi_errors = g_string_new("");
-       smiSetErrorHandler(smi_error_handler);
-
        for(i=0;i<num_smi_modules;i++) {
                if (!smi_modules[i].name) continue;
 
-
                if (smiIsLoaded(smi_modules[i].name)) {
                        continue;
                } else {
@@ -553,7 +571,10 @@ void register_mibs(void) {
 
        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);
+                                          "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));
        }
 
@@ -566,6 +587,18 @@ 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)
+                       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)) {
@@ -581,9 +614,7 @@ void register_mibs(void) {
                                                       key,
                                                       smiNode->oidlen,
                                                       smiNode->oid);
-#ifndef WIN32
-                       free (oid);
-#endif
+                       smi_free (oid);
 
                        D(4,("\t\tNode: kind=%d oid=%s name=%s ",
                                 oid_data->kind, oid_subid2string(smiNode->oid, smiNode->oidlen), oid_data->name ));
@@ -597,13 +628,15 @@ void register_mibs(void) {
                                        typedata->display,
                                        NULL,
                                        0,
-#ifndef WIN32
                                        smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_ALL),
-#else
-                                       g_strdup (smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_ALL)),
-#endif
                                        HFILL }};
 
+                               /* Don't allow duplicate blurb/name */
+                               if (strcmp(hf.hfinfo.blurb, hf.hfinfo.name) == 0) {
+                                       smi_free((void *) hf.hfinfo.blurb);
+                                       hf.hfinfo.blurb = NULL;
+                               }
+
                                oid_data->value_hfid = -1;
 
                                if ( IS_ENUMABLE(hf.hfinfo.type) && (smiEnum = smiGetFirstNamedNumber(smiType))) {
@@ -619,7 +652,7 @@ void register_mibs(void) {
                                        hf.hfinfo.strings = VALS(vals->data);
                                        g_array_free(vals,FALSE);
                                }
-#if 0 /* packet-snmp does not hanldle bits yet */
+#if 0 /* packet-snmp does not handle bits yet */
                        } else if (smiType->basetype == SMI_BASETYPE_BITS && ( smiEnum = smiGetFirstNamedNumber(smiType) )) {
                                guint n = 0;
                                oid_bits_info_t* bits = g_malloc(sizeof(oid_bits_info_t));
@@ -640,7 +673,7 @@ void register_mibs(void) {
                                        guint mask = 1 << (smiEnum->value.value.integer32 % 8);
                                        char* base = alnumerize(oid_data->name);
                                        char* ext = alnumerize(smiEnum->name);
-                                       hf_register_info hf2 = { &(bits->data[n].hfid), { NULL, NULL, FT_UINT8, BASE_HEX, NULL, mask, "", HFILL }};
+                                       hf_register_info hf2 = { &(bits->data[n].hfid), { NULL, NULL, FT_UINT8, BASE_HEX, NULL, mask, NULL, HFILL }};
 
                                        bits->data[n].hfid = -1;
                                        bits->data[n].offset = smiEnum->value.value.integer32 / 8;
@@ -665,7 +698,7 @@ void register_mibs(void) {
                                                key->display,
                                                NULL,
                                                0,
-                                               "",
+                                               NULL,
                                                HFILL }};
 
                                        D(5,("\t\t\tIndex: name=%s subids=%d key_type=%d",
@@ -711,7 +744,7 @@ const char* oid_subid2string(guint32* subids, guint len) {
                return "*** Empty OID ***";
 
        do {
-               w += sprintf(w,"%u.",*subids++);
+               w += g_snprintf(w,12,"%u.",*subids++);
        } while(--len);
 
        if (w!=s) *(w-1) = '\0'; else *(s) = '\0';
@@ -725,7 +758,7 @@ guint check_num_oid(const char* str) {
        guint n = 0;
 
        D(8,("check_num_oid: '%s'",str));
-       if (*r == '.' || *r == '\0') return 0;
+       if (!r || *r == '.' || *r == '\0') return 0;
 
        do {
                D(9,("\tcheck_num_oid: '%c' %d",*r,n));
@@ -894,7 +927,6 @@ guint oid_subid2encoded(guint subids_len, guint32* subids, guint8** bytes_p) {
        guint bytelen = 0;
        guint i;
        guint32 subid;
-       guint8* bytes;
        guint8* b;
 
        if ( !subids || subids_len <= 0) {
@@ -921,7 +953,7 @@ guint oid_subid2encoded(guint subids_len, guint32* subids, guint8** bytes_p) {
                        subid = subids[i];
        } while ( i++ < subids_len );
 
-       *bytes_p = b = bytes = ep_alloc(bytelen);
+       *bytes_p = b = ep_alloc(bytelen);
 
        subid = (subids[0] * 40) + subids[1];
        i = 2;
@@ -1049,19 +1081,23 @@ oid_get_default_mib_path(void) {
        guint i;
 
        path_str = g_string_new("");
-#ifdef WIN32
+#ifdef _WIN32
 #define PATH_SEPARATOR ";"
        path = get_datafile_path("snmp\\mibs");
-       g_string_sprintfa(path_str, "%s;", path);
+       g_string_append_printf(path_str, "%s;", path);
        g_free (path);
 
        path = get_persconffile_path("snmp\\mibs", FALSE, FALSE);
-       g_string_sprintfa(path_str, "%s", path);
+       g_string_append_printf(path_str, "%s", path);
        g_free (path);
 #else
 #define PATH_SEPARATOR ":"
        path = smiGetPath();
-       g_string_sprintfa(path_str, "%s", path);
+       g_string_append(path_str, "/usr/share/snmp/mibs");
+       if (strlen(path) > 0 ) {
+               g_string_append(path_str, PATH_SEPARATOR);
+       }
+       g_string_append_printf(path_str, "%s", path);
        free (path);
 #endif
 
@@ -1069,7 +1105,7 @@ oid_get_default_mib_path(void) {
                if (!( smi_paths[i].name && *smi_paths[i].name))
                        continue;
 
-               g_string_sprintfa(path_str,PATH_SEPARATOR "%s",smi_paths[i].name);
+               g_string_append_printf(path_str,PATH_SEPARATOR "%s",smi_paths[i].name);
        }
 
        path_ret = path_str->str;
@@ -1145,7 +1181,7 @@ void add_oid_debug_subtree(oid_info_t* oid_info, proto_tree *tree) {
  * Local Variables:
  * c-basic-offset: 8
  * tab-width: 8
- * indent-tabs-mode: tabs
+ * indent-tabs-mode: t
  * End:
  *
  * ex: set shiftwidth=8 tabstop=8 noexpandtab