get libsmi into the picture
[obnox/wireshark/wip.git] / epan / oids.c
index 2f4430a8e34f8f75b35f8a2b4b921b28301dee01..8ae72b23b8daa25e1bb8673e645c2e03e76dbbb2 100644 (file)
@@ -41,7 +41,7 @@
 #include "filesystem.h"
 #include "dissectors/packet-ber.h"
 
-#ifdef HAVE_SMI
+#ifdef HAVE_LIBSMI
 #include <smi.h>
 #endif
 
@@ -69,12 +69,28 @@ static const oid_value_type_t string_type =     { FT_STRING, BASE_NONE, BER_CLAS
 static const oid_value_type_t unknown_type =    { FT_BYTES,  BASE_NONE, BER_CLASS_ANY, BER_TAG_ANY,             0,  -1, OID_KEY_TYPE_WRONG,   OID_KEY_TYPE_WRONG,       0};
 
 static oid_info_t oid_root = { 0, NULL, OID_KIND_UNKNOWN, NULL, &unknown_type, -2, NULL, NULL, NULL};
-static emem_tree_t* oids_by_name = NULL;
 
-static oid_info_t* add_oid(char* name, oid_kind_t kind, const oid_value_type_t* type, oid_key_t* key, guint oid_len, guint32 *subids) {
+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;
+       
+       if (!oid_root.children) {
+               char* debug_env = getenv("WIRESHARK_DEBUG_MIBS");
+               guint32 subid;
+               
+               debuglevel = debug_env ? strtoul(debug_env,NULL,10) : 0;
+                               
+               oid_root.children = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_root");
                
+               /*
+                * make sure we got strings at least in the three root-children oids
+                * that way oid_resolved() will always have a string to print
+                */
+               subid = 0; oid_add("itu-t",1,&subid);
+               subid = 1; oid_add("iso",1,&subid);
+               subid = 2; oid_add("joint-iso-itu-t",1,&subid);
+       }
+       
        oid_len--;
        
        do {
@@ -82,10 +98,13 @@ static oid_info_t* add_oid(char* name, oid_kind_t kind, const oid_value_type_t*
                
                if(n) {
                        if (i == oid_len) {
-                               if (! n->name) {
-                                       n->name = g_strdup(name);
+                               if (n->name) {
+                                       D(2,("Renaming Oid from: %s -> %s, this menas the same oid is registered more than once",n->name,name));
+                                       g_free(n->name);
                                }
                                
+                               n->name = g_strdup(name);
+
                                if (! n->value_type) {
                                        n->value_type = type;
                                }
@@ -107,12 +126,12 @@ static oid_info_t* add_oid(char* name, oid_kind_t kind, const oid_value_type_t*
                        if (i == oid_len) {
                                n->name = g_strdup(name);
                                n->value_type = type;
-                               n->kind = OID_KIND_UNKNOWN;
+                               n->kind = kind;
                                return n;
                        } else {
-                               n->name = g_strdup(name);
+                               n->name = NULL;
                                n->value_type = NULL;
-                               n->kind = kind;
+                               n->kind = OID_KIND_UNKNOWN;
                        }
                }
                c = n;
@@ -122,11 +141,41 @@ static oid_info_t* add_oid(char* name, oid_kind_t kind, const oid_value_type_t*
        return NULL;
 }
 
-extern void oid_add(char* name, guint oid_len, guint32 *subids) {
-       add_oid(name,OID_KIND_UNKNOWN,&unknown_type,NULL,oid_len,subids);
+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)));
+               add_oid(name,OID_KIND_UNKNOWN,NULL,NULL,oid_len,subids);
+       } else {
+               D(1,("Failed to add Oid: %s (from subids)",name?name:"NULL"));
+       }
+}
+
+void oid_add_from_string(const char* name, const gchar *oid_str) {
+       guint32* subids;
+       guint oid_len = oid_string2subid(oid_str, &subids); 
+       
+       if (oid_len) {
+               D(3,("\tOid (from string): %s %s ",name?name:"NULL", oid_subid2string(subids,oid_len)));
+               add_oid(name,OID_KIND_UNKNOWN,NULL,NULL,oid_len,subids);
+       } else {
+               D(1,("Failed to add Oid: %s %s ",name?name:"NULL", oid_str?oid_str:NULL));
+       }
+}
+
+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);
+
+       if (subids_len) {
+               D(3,("\tOid (from encoded): %s %s ",name, oid_subid2string(subids,subids_len)));
+               add_oid(name,OID_KIND_UNKNOWN,NULL,NULL,subids_len,subids);
+       } else {
+               D(1,("Failed to add Oid: %s [%d]%s ",name?name:"NULL", oid_len,bytestring_to_str(oid, oid_len, ':')));
+       }
 }
 
-#ifdef HAVE_SMI
+#ifdef HAVE_LIBSMI
 typedef struct smi_module_t {
        char* name;
 } smi_module_t;
@@ -240,6 +289,7 @@ static inline oid_kind_t smikind(SmiNode* sN, oid_key_t** key_p) {
                case SMI_NODEKIND_ROW: {
                        SmiElement* sE;
                        oid_key_t* kl = NULL;
+                       const oid_value_type_t* typedata = NULL;
                        
                        switch (sN->indexkind) {
                                case SMI_INDEX_INDEX:
@@ -252,11 +302,22 @@ static inline oid_kind_t smikind(SmiNode* sN, oid_key_t** key_p) {
                                        return OID_KIND_UNKNOWN;
                        };
                        
+                       
+                       
                        for (sE = smiGetFirstElement(sN); sE; sE = smiGetNextElement(sE)) {
                                SmiNode* elNode =  smiGetElementNode(sE) ;
                                SmiType* elType = smiGetNodeType(elNode);
                                oid_key_t* k;
-                               const oid_value_type_t* typedata =  get_typedata(elType);
+                               guint non_implicit_size = 0;
+                               
+                               if (elType) {
+                                       non_implicit_size = smiGetMinSize(elType);
+                                       if (non_implicit_size == smiGetMaxSize(elType)) {
+                                               non_implicit_size = 0;
+                                       }
+                               }
+                               
+                               typedata =  get_typedata(elType);
                                
                                k = g_malloc(sizeof(oid_key_t));
                                
@@ -265,21 +326,22 @@ static inline oid_kind_t smikind(SmiNode* sN, oid_key_t** key_p) {
                                                                                  smiRenderOID(elNode->oidlen, elNode->oid, SMI_RENDER_NAME));
                                k->hfid = -2;
                                k->ft_type = typedata ? typedata->ft_type : FT_BYTES;
-                               k->ft_type = typedata ? typedata->display : BASE_NONE;
+                               k->display = typedata ? typedata->display : BASE_NONE;
                                k->next = NULL;
                                
                                                                
                                if (typedata) {
-                                       k->key_type = elNode->implied ? typedata->keytype_implicit : typedata->keytype;
+                                       k->key_type = typedata->keytype;
                                        k->num_subids = typedata->keysize;
                                } else {
                                        if (elType) {
                                                switch (elType->basetype) {
                                                        case SMI_BASETYPE_BITS:
-                                                       case SMI_BASETYPE_OCTETSTRING:
-                                                               k->key_type = elNode->implied ? OID_KEY_TYPE_BYTES : OID_KEY_TYPE_WRONG;
-                                                               k->num_subids = 0;
+                                                       case SMI_BASETYPE_OCTETSTRING: {
+                                                               k->key_type = OID_KEY_TYPE_BYTES;
+                                                               k->num_subids = non_implicit_size; 
                                                                break;
+                                                       } 
                                                        case SMI_BASETYPE_ENUM:
                                                        case SMI_BASETYPE_OBJECTIDENTIFIER:
                                                        case SMI_BASETYPE_INTEGER32:
@@ -307,6 +369,23 @@ static inline oid_kind_t smikind(SmiNode* sN, oid_key_t** key_p) {
                                kl = k;
                        }
                        
+                       if (sN->implied) {
+                               if (typedata) {
+                                       kl->key_type = typedata->keytype_implicit;
+                               } else switch (kl->key_type) {
+                                       case OID_KEY_TYPE_BYTES:
+                                               if (kl->num_subids)
+                                                       kl->key_type = OID_KEY_TYPE_FIXED_BYTES;
+                                               break;
+                                       case OID_KEY_TYPE_STRING:
+                                               if (kl->num_subids)
+                                                       kl->key_type = OID_KEY_TYPE_FIXED_STRING;
+                                               break;
+                                       default:
+                                               break;
+                               }
+                       
+                       }
                        return OID_KIND_ROW;
                }
                case SMI_NODEKIND_NODE: return OID_KIND_NODE;
@@ -325,6 +404,12 @@ 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) )
 
+#ifdef WIN32
+#define PATH_SEPARATOR ";"
+#else
+#define PATH_SEPARATOR ":"
+#endif
+
 void register_mibs(void) {
        SmiModule *smiModule;
     SmiNode *smiNode;
@@ -343,9 +428,6 @@ void register_mibs(void) {
        };
        char* smi_load_error = NULL;
        GString* path_str;
-       char* debug_env = getenv("WIRESHARK_DEBUG_MIBS");
-       
-       debuglevel = debug_env ? strtoul(debug_env,NULL,10) : 0;
        
        smi_modules_uat = uat_new("SMI Modules",
                                                          sizeof(smi_module_t),
@@ -387,13 +469,13 @@ void register_mibs(void) {
        }
        
        path_str = g_string_new(get_datafile_path("mibs"));
-       g_string_sprintfa(path_str,":%s",get_persconffile_path("mibs", FALSE));
+       g_string_sprintfa(path_str,PATH_SEPARATOR "%s",get_persconffile_path("mibs", FALSE));
 
        for(i=0;i<num_smi_paths;i++) {
                if (!( smi_paths[i].name && *smi_paths[i].name))
                        continue;
                
-               g_string_sprintfa(path_str,":%s",smi_paths[i].name);
+               g_string_sprintfa(path_str,PATH_SEPARATOR "%s",smi_paths[i].name);
        }
        
        D(1,("SMI Path: '%s'",path_str->str));
@@ -441,9 +523,8 @@ void register_mibs(void) {
                                                                                   smiNode->oid);
                        
                        
-                       D(4,("\t\tNode: subid=%u name=%s kind=%d",
-                                oid_data->subid, oid_data->name, oid_data->kind
-                                ));
+                       D(4,("\t\tNode: kind=%d oid=%s name=%s ",
+                                oid_data->kind, oid_subid2string(smiNode->oid, smiNode->oidlen), oid_data->name ));
                        
                        if ( typedata && oid_data->value_hfid == -2 ) {
                                SmiNamedNumber* smiEnum; 
@@ -560,12 +641,11 @@ void register_mibs(void) {
 #endif
 
 
-void oid_init(void) {
-       oid_root.children = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_root");
-       oids_by_name = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_names");
-       
-#ifdef HAVE_SMI
+void oids_init(void) {
+#ifdef HAVE_LIBSMI
        register_mibs();
+#else
+       D(1,("libsmi disabled oid resolution not enabled"));
 #endif
 }
 
@@ -573,6 +653,8 @@ const char* oid_subid2string(guint32* subids, guint len) {
        char* s = ep_alloc0(len*11);
        char* w = s;
        
+       DISSECTOR_ASSERT(subids);
+
        do {
                w += sprintf(w,"%u.",*subids++);
        } while(--len);
@@ -587,10 +669,12 @@ guint check_num_oid(const char* str) {
        char c = '\0';
        guint n = 0;
        
-       if (*r == '.') return 0;
+       D(8,("check_num_oid: '%s'",str));
+       if (*r == '.' || *r == '\0') return 0;
        
        do {
-               switch(*r++) {
+               D(9,("\tcheck_num_oid: '%c' %d",*r,n));
+               switch(*r) {
                        case '.':
                                n++;
                                if (c == '.') return 0; 
@@ -598,12 +682,12 @@ guint check_num_oid(const char* str) {
                        case '6' : case '7' : case '8' : case '9' : case '0' :
                                continue;
                        case '\0':
+                               n++;
                                break;
                        default:
                                return 0;
                } 
-               c = *r;
-       } while(1);
+       } while((c = *r++));
        
        if (c == '.') return 0;
        
@@ -613,21 +697,25 @@ guint check_num_oid(const char* str) {
 guint oid_string2subid(const char* str, guint32** subids_p) {
        const char* r = str;
        guint32* subids;
+       guint32* subids_overflow;
        guint n = check_num_oid(str);
        
+       D(6,("oid_string2subid: str='%s'",str));
+
        if (!n) {
                *subids_p = NULL;
                return 0;
        }
-       
-       *subids_p = subids = ep_alloc_array(guint32,n);
-       
+
+       *subids_p = subids = ep_alloc0(sizeof(guint32)*n);
+       subids_overflow = subids + n;
        do switch(*r) {
                case '.':
                        subids++;
                        continue;
                case '1' : case '2' : case '3' : case '4' : case '5' : 
                case '6' : case '7' : case '8' : case '9' : case '0' :
+                       DISSECTOR_ASSERT(subids < subids_overflow);
                        *(subids) *= 10;
                        *(subids) += *r - '0';
                        continue;
@@ -635,7 +723,7 @@ guint oid_string2subid(const char* str, guint32** subids_p) {
                        break;
                default:
                        return 0;
-       } while(1);
+       } while(*r++);
        
        return n;
 }
@@ -647,10 +735,12 @@ guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_
        guint32 subid = 0;
        gboolean is_first = TRUE;
        guint32* subids;
-       
+       guint32* subid_overflow;
+               
        for (i=0; i<oid_len; i++) { if (! (oid_bytes[i] & 0x80 )) n++; }
        
        *subids_p = subids = ep_alloc(sizeof(guint32)*n);
+       subid_overflow = subids+n;
        
        for (i=0; i<oid_len; i++){
                guint8 byte = oid_bytes[i];
@@ -673,6 +763,7 @@ guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_
                        is_first = FALSE;
                }
                
+               DISSECTOR_ASSERT(subids < subid_overflow);
                *subids++ = subid;
                subid = 0;
        }
@@ -684,6 +775,8 @@ oid_info_t* oid_get(guint len, guint32* subids, guint* matched, guint* left) {
        oid_info_t* curr_oid = &oid_root;
        guint i;
        
+       DISSECTOR_ASSERT(subids && *subids <= 2);
+
        for( i=0; i < len; i++) {
                oid_info_t* next_oid = emem_tree_lookup32(curr_oid->children,subids[i]);
                if (next_oid) {
@@ -710,18 +803,8 @@ oid_info_t* oid_get_from_string(const gchar *oid_str, guint32** subids_p, guint*
 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);
-       guint matched;
-       guint left;
-       oid_info_t* curr_oid = oid_get(subid_oid_length, subid_oid, &matched, &left);
-               
-               if (matched == subid_oid_length) {
-                       return curr_oid->name;
-               } else {
-                       return ep_strdup_printf("%s.%s",
-                                                                       curr_oid->name,
-                                                                       oid_subid2string(&(subid_oid[matched]),left) );
-               }
        
+       return oid_resolved(subid_oid_length, subid_oid);
 }
 
 
@@ -732,6 +815,8 @@ guint oid_subid2encoded(guint subids_len, guint32* subids, guint8** bytes_p) {
        guint8* bytes;
        guint8* b;
        
+       DISSECTOR_ASSERT(subids && *subids <= 2);
+
        if (subids_len < 2) {
                *bytes_p = NULL;
                return 0;
@@ -820,17 +905,10 @@ char* oid2str(oid_info_t* oid, guint32* subids, guint len, guint left) {
 }
 
 const gchar *oid_resolved_from_string(const gchar *oid_str) {
-       guint32* subids;
-       guint num_subids = oid_string2subid(oid_str, &subids);
+       guint32 *subid_oid;
+       guint subid_oid_length = oid_string2subid(oid_str, &subid_oid);
        
-       if (num_subids) {
-               guint matched;
-               guint left;
-               oid_info_t* oid = oid_get(num_subids, subids, &matched, &left);
-               return oid2str(oid, subids, num_subids, left);
-       } else {
-               return emem_tree_lookup_string(oids_by_name, oid_str);
-       }
+       return oid_resolved(subid_oid_length, subid_oid);
 }
 
 extern char* oid_test_a2b(guint32 num_subids, guint32* subids);
@@ -865,7 +943,11 @@ char* oid_test_a2b(guint32 num_subids, guint32* subids) {
 const gchar *oid_resolved(guint32 num_subids, guint32* subids) {
        guint matched;
        guint left;
-       oid_info_t* oid = oid_get(num_subids, subids, &matched, &left);
+       oid_info_t* oid;
+
+       DISSECTOR_ASSERT(subids && *subids <= 2);
+
+       oid = oid_get(num_subids, subids, &matched, &left);
        
        while (! oid->name ) {
                if (!(oid = oid->parent)) {
@@ -877,10 +959,29 @@ const gchar *oid_resolved(guint32 num_subids, guint32* subids) {
        
        if (left) {
                return ep_strdup_printf("%s.%s",
-                                                               oid->name,
+                                                               oid->name ? oid->name : oid_subid2string(subids,matched),
                                                                oid_subid2string(&(subids[matched]),left));
        } else {
-               return oid->name;
+               return oid->name ? oid->name : oid_subid2string(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_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_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);
+}
+