/* 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$
*
#ifdef HAVE_LIBSMI
#include <smi.h>
+
+static gboolean oids_init_done = 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.
+ */
+
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};
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 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};
#ifdef HAVE_LIBSMI
/* de-allocate storage mallocated by libsmi */
/* */
-/* XXX: On Windows we can use free() only if the Windows libsmi.dll */
-/* being used is linked with the same CRTL as wireshark. */
-/* As a temporary hack we'll assume on Windows that the Wireshark */
-/* build of libsmi.dll was done with VC6/msvcrt.dll (as is */
-/* currently the case). If wireshark is being built with */
-/* vc6 (which is also currently the case for the standard */
-/* wireshark release). we can use free(). */
-/* If vc6 is not being used here, then we'll just have to live */
-/* with a memory leak for now. */
-/* Note: A permanent fix would probably be for libsmi to include */
-/* its' existing smiFree function as part of the libsmi API so */
-/* wireshark can call it to free 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 !defined _WIN32 || (_MSC_VER == 1200)
- free(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
}
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_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 : "-",
}
-static void* smi_mod_copy_cb(void* dest, const void* orig, unsigned len _U_) {
+static void* smi_mod_copy_cb(void* dest, const void* orig, size_t len _U_) {
const smi_module_t* m = orig;
smi_module_t* d = dest;
static void smi_mod_free_cb(void* p) {
smi_module_t* m = p;
- if (m->name) g_free(m->name);
+ g_free(m->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,
* 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[] = {
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;
|| (ft == FT_INT8) || (ft == FT_INT16) || (ft == FT_INT24) || (ft == FT_INT32) \
|| (ft == FT_UINT64) || (ft == FT_INT64) )
-void register_mibs(void) {
+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;
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_DIRECTORYNAME(smi_mod,name,"Directory path","The directory name"),
UAT_END_FIELDS
};
char* smi_load_error = NULL;
smi_mod_copy_cb,
NULL,
smi_mod_free_cb,
+ restart_needed_warning,
smi_fields);
smi_paths_uat = uat_new("SMI Paths",
smi_mod_copy_cb,
NULL,
smi_mod_free_cb,
+ restart_needed_warning,
smi_paths_fields);
- smiInit(NULL);
-
uat_load(smi_modules_uat, &smi_load_error);
if (smi_load_error) {
return;
}
- path_str = oid_get_default_mib_path();
- D(1,("SMI Path: '%s'",path_str));
-
- smiSetPath(path_str);
+ if (!prefs.load_smi_modules) {
+ D(1,("OID resolution not enabled"));
+ return;
+ }
+ /* 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;
+ }
+ smiInit(NULL);
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);
+
for(i=0;i<num_smi_modules;i++) {
if (!smi_modules[i].name) continue;
-
if (smiIsLoaded(smi_modules[i].name)) {
continue;
} else {
}
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 (!prefs.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));
}
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 (!prefs.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)) {
typedata->display,
NULL,
0,
-#if !defined _WIN32 || (_MSC_VER == 1200)
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))) {
}
}
- 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 */
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;
key->display,
NULL,
0,
- "",
+ NULL,
HFILL }};
D(5,("\t\t\tIndex: name=%s subids=%d key_type=%d",
proto_mibs = proto_register_protocol("MIBs", "MIBS", "mibs");
- proto_register_field_array(proto_mibs, (hf_register_info*)hfa->data, hfa->len);
+ proto_register_field_array(proto_mibs, (hf_register_info*)(void*)hfa->data, hfa->len);
- proto_register_subtree_array((gint**)etta->data, etta->len);
+ proto_register_subtree_array((gint**)(void*)etta->data, etta->len);
g_array_free(etta,TRUE);
#endif
}
+void oids_cleanup(void) {
+#ifdef HAVE_LIBSMI
+ unregister_mibs();
+#else
+ D(1,("libsmi disabled oid resolution not enabled"));
+#endif
+}
+
const char* oid_subid2string(guint32* subids, guint len) {
char* s = ep_alloc0(((len)*11)+1);
char* w = s;
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';
return s;
}
-guint check_num_oid(const char* str) {
+static guint check_num_oid(const char* str) {
const char* r = str;
char c = '\0';
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));
guint bytelen = 0;
guint i;
guint32 subid;
- guint8* bytes;
guint8* b;
if ( !subids || subids_len <= 0) {
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;
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 & 0x00003F10) >> 7) | 0x80;
+ case 1: *(b++) = subid & 0x0000007F ; break;
}
subid = subids[i];
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));
- }
-}
-
const gchar *oid_resolved_from_string(const gchar *oid_str) {
guint32 *subid_oid;
guint subid_oid_length = oid_string2subid(oid_str, &subid_oid);
guint i;
path_str = g_string_new("");
+
+ if (!prefs.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_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
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;
* 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
+ * ex: set shiftwidth=8 tabstop=8 noexpandtab:
* :indentSize=8:tabSize=8:noTabs=false:
*/