2 * Object IDentifier Support
4 * (c) 2007, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 #include "report_err.h"
42 #include "filesystem.h"
43 #include "dissectors/packet-ber.h"
49 #define D(level,args) do if (debuglevel >= level) { printf args; printf("\n"); fflush(stdout); } while(0)
53 static int debuglevel = 0;
55 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};
56 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};
57 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};
58 static const oid_value_type_t ipv4_type = { FT_IPv4, BASE_NONE, BER_CLASS_APP, 0, 4, 4, OID_KEY_TYPE_IPADDR, 4};
59 static const oid_value_type_t counter32_type = { FT_UINT64, BASE_DEC, BER_CLASS_APP, 1, 1, 5, OID_KEY_TYPE_INTEGER, 1};
60 static const oid_value_type_t unsigned32_type = { FT_UINT32, BASE_DEC, BER_CLASS_APP, 2, 1, 4, OID_KEY_TYPE_INTEGER, 1};
61 /*static const oid_value_type_t timeticks_type = { FT_UINT32, BASE_DEC, BER_CLASS_APP, 3, 1, 4, OID_KEY_TYPE_INTEGER, 1};
62 * TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
63 * If the BER encoding should not have the top bit set as to not become a negative number
64 * the ber encoding may take 5 octets to encode.
66 static const oid_value_type_t timeticks_type = { FT_UINT64, BASE_DEC, BER_CLASS_APP, 3, 1, 5, OID_KEY_TYPE_INTEGER, 1};
67 static const oid_value_type_t opaque_type = { FT_BYTES, BASE_NONE, BER_CLASS_APP, 4, 1, 4, OID_KEY_TYPE_BYTES, 0};
68 static const oid_value_type_t nsap_type = { FT_BYTES, BASE_NONE, BER_CLASS_APP, 5, 0, -1, OID_KEY_TYPE_NSAP, 0};
69 static const oid_value_type_t counter64_type = { FT_UINT64, BASE_DEC, BER_CLASS_APP, 6, 1, 8, OID_KEY_TYPE_INTEGER, 1};
70 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};
71 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};
72 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};
73 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};
74 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};
75 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};
77 static oid_info_t oid_root = { 0, NULL, OID_KIND_UNKNOWN, NULL, &unknown_type, -2, NULL, NULL, NULL};
79 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) {
81 oid_info_t* c = &oid_root;
83 if (!oid_root.children) {
84 char* debug_env = getenv("WIRESHARK_DEBUG_MIBS");
87 debuglevel = debug_env ? strtoul(debug_env,NULL,10) : 0;
89 oid_root.children = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_root");
92 * make sure we got strings at least in the three root-children oids
93 * that way oid_resolved() will always have a string to print
95 subid = 0; oid_add("itu-t",1,&subid);
96 subid = 1; oid_add("iso",1,&subid);
97 subid = 2; oid_add("joint-iso-itu-t",1,&subid);
103 oid_info_t* n = emem_tree_lookup32(c->children,subids[i]);
108 if (!g_str_equal(n->name,name)) {
109 D(2,("Renaming Oid from: %s -> %s, this means the same oid is registered more than once",n->name,name));
111 /* XXX - Don't free n->name here. It may be part of an hf_register_info
112 * struct that has been appended to the hfa GArray. */
115 n->name = g_strdup(name);
117 if (! n->value_type) {
118 n->value_type = type;
124 n = g_malloc(sizeof(oid_info_t));
125 n->subid = subids[i];
127 n->children = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_children");
133 emem_tree_insert32(c->children,n->subid,n);
136 n->name = g_strdup(name);
137 n->value_type = type;
142 n->value_type = NULL;
143 n->kind = OID_KIND_UNKNOWN;
149 g_assert_not_reached();
153 void oid_add(const char* name, guint oid_len, guint32 *subids) {
154 g_assert(subids && *subids <= 2);
156 D(3,("\tOid (from subids): %s %s ",name?name:"NULL", oid_subid2string(subids,oid_len)));
157 add_oid(name,OID_KIND_UNKNOWN,NULL,NULL,oid_len,subids);
159 D(1,("Failed to add Oid: %s (from subids)",name?name:"NULL"));
163 void oid_add_from_string(const char* name, const gchar *oid_str) {
165 guint oid_len = oid_string2subid(oid_str, &subids);
168 D(3,("\tOid (from string): %s %s ",name?name:"NULL", oid_subid2string(subids,oid_len)));
169 add_oid(name,OID_KIND_UNKNOWN,NULL,NULL,oid_len,subids);
171 D(1,("Failed to add Oid: %s %s ",name?name:"NULL", oid_str?oid_str:NULL));
175 extern void oid_add_from_encoded(const char* name, const guint8 *oid, gint oid_len) {
177 guint subids_len = oid_encoded2subid(oid, oid_len, &subids);
180 D(3,("\tOid (from encoded): %s %s ",name, oid_subid2string(subids,subids_len)));
181 add_oid(name,OID_KIND_UNKNOWN,NULL,NULL,subids_len,subids);
183 D(1,("Failed to add Oid: %s [%d]%s ",name?name:"NULL", oid_len,bytestring_to_str(oid, oid_len, ':')));
188 /* de-allocate storage mallocated by libsmi */
190 /* XXX: On Windows we can use free() only if the Windows libsmi.dll */
191 /* being used is linked with the same CRTL as wireshark. */
192 /* As a temporary hack we'll assume on Windows that the Wireshark */
193 /* build of libsmi.dll was done with VC6/msvcrt.dll (as is */
194 /* currently the case). If wireshark is being built with */
195 /* vc6 (which is also currently the case for the standard */
196 /* wireshark release). we can use free(). */
197 /* If vc6 is not being used here, then we'll just have to live */
198 /* with a memory leak for now. */
199 /* Note: A permanent fix would probably be for libsmi to include */
200 /* its' existing smiFree function as part of the libsmi API so */
201 /* wireshark can call it to free storage mallocated by libsmi. */
203 static void smi_free(void *ptr) {
204 #if !defined _WIN32 || (_MSC_VER == 1200)
210 typedef struct smi_module_t {
214 static smi_module_t* smi_paths = NULL;
215 static guint num_smi_paths = 0;
216 static uat_t* smi_paths_uat = NULL;
218 static smi_module_t* smi_modules = NULL;
219 static guint num_smi_modules = 0;
220 static uat_t* smi_modules_uat = NULL;
222 static GString* smi_errors;
224 UAT_CSTRING_CB_DEF(smi_mod,name,smi_module_t)
226 static void smi_error_handler(char *path, int line, int severity, char *msg, char *tag) {
227 g_string_sprintfa(smi_errors,"%s:%d %d %s %s\n",
235 static void* smi_mod_copy_cb(void* dest, const void* orig, unsigned len _U_) {
236 const smi_module_t* m = orig;
237 smi_module_t* d = dest;
239 d->name = g_strdup(m->name);
244 static void smi_mod_free_cb(void* p) {
246 if (m->name) g_free(m->name);
250 static char* alnumerize(const char* name) {
251 char* s = g_strdup(name);
256 for (;(c = *r); r++) {
257 if (isalnum(c) || c == '_' || c == '-' || c == '.') {
259 } else if (c == ':' && r[1] == ':') {
269 const oid_value_type_t* get_typedata(SmiType* smiType) {
271 * There has to be a better way to know if a given
272 * OCTETSTRING type is actually human readable text,
273 * an address of some type or some moe specific FT_
274 * Until that is found, this is the mappping between
275 * SNMP Types and our FT_s
277 static const struct _type_mapping_t {
280 const oid_value_type_t* type;
282 {"IpAddress", SMI_BASETYPE_UNKNOWN, &ipv4_type},
283 {"InetAddressIPv4",SMI_BASETYPE_UNKNOWN,&ipv4_type},
284 {"InetAddressIPv6",SMI_BASETYPE_UNKNOWN,&ipv6_type},
285 {"NetworkAddress",SMI_BASETYPE_UNKNOWN,&ipv4_type},
286 {"MacAddress",SMI_BASETYPE_UNKNOWN,ðer_type},
287 {"TimeTicks",SMI_BASETYPE_UNKNOWN,&timeticks_type},
288 {"Ipv6Address",SMI_BASETYPE_UNKNOWN,&ipv6_type},
289 {"TimeStamp",SMI_BASETYPE_UNKNOWN,&timeticks_type},
290 {"DisplayString",SMI_BASETYPE_UNKNOWN,&string_type},
291 {"SnmpAdminString",SMI_BASETYPE_UNKNOWN,&string_type},
292 {"DateAndTime",SMI_BASETYPE_UNKNOWN,&string_type},
293 {"Counter",SMI_BASETYPE_UNKNOWN,&counter32_type},
294 {"Counter32",SMI_BASETYPE_UNKNOWN,&counter32_type},
295 {"Unsigned32",SMI_BASETYPE_UNKNOWN,&unsigned32_type},
296 {"Gauge",SMI_BASETYPE_UNKNOWN,&unsigned32_type},
297 {"Gauge32",SMI_BASETYPE_UNKNOWN,&unsigned32_type},
298 {"NsapAddress",SMI_BASETYPE_UNKNOWN,&nsap_type},
299 {"i32",SMI_BASETYPE_INTEGER32,&integer_type},
300 {"octets",SMI_BASETYPE_OCTETSTRING,&bytes_type},
301 {"oid",SMI_BASETYPE_OBJECTIDENTIFIER,&oid_type},
302 {"u32",SMI_BASETYPE_UNSIGNED32,&unsigned32_type},
303 {"u64",SMI_BASETYPE_UNSIGNED64,&counter64_type},
304 {"f32",SMI_BASETYPE_FLOAT32,&float_type},
305 {"f64",SMI_BASETYPE_FLOAT64,&double_type},
306 {"f128",SMI_BASETYPE_FLOAT128,&bytes_type},
307 {"enum",SMI_BASETYPE_ENUM,&integer_type},
308 {"bits",SMI_BASETYPE_BITS,&bytes_type},
309 {"unk",SMI_BASETYPE_UNKNOWN,&unknown_type},
312 const struct _type_mapping_t* t;
313 SmiType* sT = smiType;
315 if (!smiType) return NULL;
318 for (t = types; t->type ; t++ ) {
319 char* name = smiRenderType(sT, SMI_RENDER_NAME);
320 if (name && t->name && g_str_equal(name, t->name )) {
328 } while(( sT = smiGetParentType(sT) ));
330 for (t = types; t->type ; t++ ) {
331 if(smiType->basetype == t->base) {
336 return &unknown_type;
339 static guint get_non_implicit_size(SmiType* sT) {
341 guint size = 0xffffffff;
343 switch (sT->basetype) {
344 case SMI_BASETYPE_OCTETSTRING:
345 case SMI_BASETYPE_OBJECTIDENTIFIER:
351 for ( ; sT; sT = smiGetParentType(sT) ) {
352 for (sR = smiGetFirstRange(sT); sR ; sR = smiGetNextRange(sR)) {
353 if (size == 0xffffffff) {
354 if (sR->minValue.value.unsigned32 == sR->maxValue.value.unsigned32) {
355 size = sR->minValue.value.unsigned32;
360 if (sR->minValue.value.unsigned32 != size || sR->maxValue.value.unsigned32 != size) {
367 return size == 0xffffffff ? 0 : size;
371 static inline oid_kind_t smikind(SmiNode* sN, oid_key_t** key_p) {
374 switch(sN->nodekind) {
375 case SMI_NODEKIND_ROW: {
377 oid_key_t* kl = NULL;
378 const oid_value_type_t* typedata = NULL;
381 switch (sN->indexkind) {
382 case SMI_INDEX_INDEX:
384 case SMI_INDEX_AUGMENT:
385 case SMI_INDEX_REORDER:
386 case SMI_INDEX_SPARSE:
387 case SMI_INDEX_EXPAND:
388 sN = smiGetRelatedNode(sN);
390 case SMI_INDEX_UNKNOWN:
391 return OID_KIND_UNKNOWN;
394 implied = sN->implied;
396 for (sE = smiGetFirstElement(sN); sE; sE = smiGetNextElement(sE)) {
397 SmiNode* elNode = smiGetElementNode(sE) ;
398 SmiType* elType = smiGetNodeType(elNode);
400 guint non_implicit_size = 0;
404 non_implicit_size = get_non_implicit_size(elType);
407 typedata = get_typedata(elType);
409 k = g_malloc(sizeof(oid_key_t));
411 oid1 = smiRenderOID(sN->oidlen, sN->oid, SMI_RENDER_QUALIFIED);
412 oid2 = smiRenderOID(elNode->oidlen, elNode->oid, SMI_RENDER_NAME);
413 k->name = g_strdup_printf("%s.%s", oid1, oid2);
418 k->ft_type = typedata ? typedata->ft_type : FT_BYTES;
419 k->display = typedata ? typedata->display : BASE_NONE;
424 k->key_type = typedata->keytype;
425 k->num_subids = typedata->keysize;
428 switch (elType->basetype) {
429 case SMI_BASETYPE_BITS:
430 case SMI_BASETYPE_OCTETSTRING: {
431 k->key_type = OID_KEY_TYPE_BYTES;
432 k->num_subids = non_implicit_size;
435 case SMI_BASETYPE_ENUM:
436 case SMI_BASETYPE_OBJECTIDENTIFIER:
437 case SMI_BASETYPE_INTEGER32:
438 case SMI_BASETYPE_UNSIGNED32:
439 case SMI_BASETYPE_INTEGER64:
440 case SMI_BASETYPE_UNSIGNED64:
441 k->key_type = OID_KEY_TYPE_INTEGER;
445 k->key_type = OID_KEY_TYPE_WRONG;
450 k->key_type = OID_KEY_TYPE_WRONG;
456 if (!*key_p) *key_p = k;
457 if (kl) kl->next = k;
463 switch (kl->key_type) {
464 case OID_KEY_TYPE_BYTES: kl->key_type = OID_KEY_TYPE_IMPLIED_BYTES; break;
465 case OID_KEY_TYPE_STRING: kl->key_type = OID_KEY_TYPE_IMPLIED_STRING; break;
466 case OID_KEY_TYPE_OID: kl->key_type = OID_KEY_TYPE_IMPLIED_OID; break;
473 case SMI_NODEKIND_NODE: return OID_KIND_NODE;
474 case SMI_NODEKIND_SCALAR: return OID_KIND_SCALAR;
475 case SMI_NODEKIND_TABLE: return OID_KIND_TABLE;
476 case SMI_NODEKIND_COLUMN: return OID_KIND_COLUMN;
477 case SMI_NODEKIND_NOTIFICATION: return OID_KIND_NOTIFICATION;
478 case SMI_NODEKIND_GROUP: return OID_KIND_GROUP;
479 case SMI_NODEKIND_COMPLIANCE: return OID_KIND_COMPLIANCE;
480 case SMI_NODEKIND_CAPABILITIES: return OID_KIND_CAPABILITIES;
481 default: return OID_KIND_UNKNOWN;
485 #define IS_ENUMABLE(ft) ( (ft == FT_UINT8) || (ft == FT_UINT16) || (ft == FT_UINT24) || (ft == FT_UINT32) \
486 || (ft == FT_INT8) || (ft == FT_INT16) || (ft == FT_INT24) || (ft == FT_INT32) \
487 || (ft == FT_UINT64) || (ft == FT_INT64) )
489 void register_mibs(void) {
490 SmiModule *smiModule;
494 GArray* hfa = g_array_new(FALSE,TRUE,sizeof(hf_register_info));
495 GArray* etta = g_array_new(FALSE,TRUE,sizeof(gint*));
496 static uat_field_t smi_fields[] = {
497 UAT_FLD_CSTRING(smi_mod,name,"The module's name"),
500 static uat_field_t smi_paths_fields[] = {
501 UAT_FLD_CSTRING(smi_mod,name,"The directory name"),
504 char* smi_load_error = NULL;
507 smi_modules_uat = uat_new("SMI Modules",
508 sizeof(smi_module_t),
520 smi_paths_uat = uat_new("SMI Paths",
521 sizeof(smi_module_t),
536 uat_load(smi_modules_uat, &smi_load_error);
538 if (smi_load_error) {
539 report_failure("Error Loading SMI Modules Table: %s",smi_load_error);
543 uat_load(smi_paths_uat, &smi_load_error);
545 if (smi_load_error) {
546 report_failure("Error Loading SMI Paths Table: %s",smi_load_error);
550 path_str = oid_get_default_mib_path();
551 D(1,("SMI Path: '%s'",path_str));
553 smiSetPath(path_str);
557 smi_errors = g_string_new("");
558 smiSetErrorHandler(smi_error_handler);
560 for(i=0;i<num_smi_modules;i++) {
561 if (!smi_modules[i].name) continue;
564 if (smiIsLoaded(smi_modules[i].name)) {
567 char* mod_name = smiLoadModule(smi_modules[i].name);
569 D(2,("Loaded: '%s'[%d] as %s",smi_modules[i].name,i,mod_name ));
571 D(1,("Failed to load: '%s'[%d]",smi_modules[i].name,i));
575 if (smi_errors->len) {
576 report_failure("The following errors were found while loading the MIBS:\n%s\n\n"
577 "The Current Path is: %s\n" , smi_errors->str , path_str);
578 D(1,("Errors while loading:\n%s\n",smi_errors->str));
582 g_string_free(smi_errors,TRUE);
584 for (smiModule = smiGetFirstModule();
586 smiModule = smiGetNextModule(smiModule)) {
588 D(3,("\tModule: %s", smiModule->name));
590 for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
592 smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
594 SmiType* smiType = smiGetNodeType(smiNode);
595 const oid_value_type_t* typedata = get_typedata(smiType);
597 oid_kind_t kind = smikind(smiNode,&key);
598 char *oid = smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_QUALIFIED);
599 oid_info_t* oid_data = add_oid(oid,
607 D(4,("\t\tNode: kind=%d oid=%s name=%s ",
608 oid_data->kind, oid_subid2string(smiNode->oid, smiNode->oidlen), oid_data->name ));
610 if ( typedata && oid_data->value_hfid == -2 ) {
611 SmiNamedNumber* smiEnum;
612 hf_register_info hf = { &(oid_data->value_hfid), {
614 alnumerize(oid_data->name),
619 #if !defined _WIN32 || (_MSC_VER == 1200)
620 smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_ALL),
622 g_strdup (smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_ALL)),
626 oid_data->value_hfid = -1;
628 if ( IS_ENUMABLE(hf.hfinfo.type) && (smiEnum = smiGetFirstNamedNumber(smiType))) {
629 GArray* vals = g_array_new(TRUE,TRUE,sizeof(value_string));
631 for(;smiEnum; smiEnum = smiGetNextNamedNumber(smiEnum)) {
633 value_string val = {smiEnum->value.value.integer32,g_strdup(smiEnum->name)};
634 g_array_append_val(vals,val);
638 hf.hfinfo.strings = VALS(vals->data);
639 g_array_free(vals,FALSE);
641 #if 0 /* packet-snmp does not handle bits yet */
642 } else if (smiType->basetype == SMI_BASETYPE_BITS && ( smiEnum = smiGetFirstNamedNumber(smiType) )) {
644 oid_bits_info_t* bits = g_malloc(sizeof(oid_bits_info_t));
645 gint* ettp = &(bits->ett);
650 g_array_append_val(etta,ettp);
652 for(;smiEnum; smiEnum = smiGetNextNamedNumber(smiEnum), bits->num++);
654 bits->data = g_malloc(sizeof(struct _oid_bit_t)*bits->num);
656 for(smiEnum = smiGetFirstNamedNumber(smiType),n=0;
658 smiEnum = smiGetNextNamedNumber(smiEnum),n++) {
659 guint mask = 1 << (smiEnum->value.value.integer32 % 8);
660 char* base = alnumerize(oid_data->name);
661 char* ext = alnumerize(smiEnum->name);
662 hf_register_info hf2 = { &(bits->data[n].hfid), { NULL, NULL, FT_UINT8, BASE_HEX, NULL, mask, "", HFILL }};
664 bits->data[n].hfid = -1;
665 bits->data[n].offset = smiEnum->value.value.integer32 / 8;
667 hf2.hfinfo.name = g_strdup_printf("%s:%s",oid_data->name,smiEnum->name);
668 hf2.hfinfo.abbrev = g_strdup_printf("%s.%s",base,ext);
672 g_array_append_val(hfa,hf2);
674 #endif /* packet-snmp does not use this yet */
675 g_array_append_val(hfa,hf);
678 if ((key = oid_data->key)) {
679 for(; key; key = key->next) {
680 hf_register_info hf = { &(key->hfid), {
682 alnumerize(key->name),
690 D(5,("\t\t\tIndex: name=%s subids=%d key_type=%d",
691 key->name, key->num_subids, key->key_type ));
693 if (key->hfid == -2) {
694 g_array_append_val(hfa,hf);
697 g_free((void*)hf.hfinfo.abbrev);
704 proto_mibs = proto_register_protocol("MIBs", "MIBS", "mibs");
706 proto_register_field_array(proto_mibs, (hf_register_info*)hfa->data, hfa->len);
708 proto_register_subtree_array((gint**)etta->data, etta->len);
711 g_array_free(etta,TRUE);
712 g_array_free(hfa,FALSE);
717 void oids_init(void) {
721 D(1,("libsmi disabled oid resolution not enabled"));
725 const char* oid_subid2string(guint32* subids, guint len) {
726 char* s = ep_alloc0(((len)*11)+1);
730 return "*** Empty OID ***";
733 w += sprintf(w,"%u.",*subids++);
736 if (w!=s) *(w-1) = '\0'; else *(s) = '\0';
741 guint check_num_oid(const char* str) {
746 D(8,("check_num_oid: '%s'",str));
747 if (*r == '.' || *r == '\0') return 0;
750 D(9,("\tcheck_num_oid: '%c' %d",*r,n));
754 if (c == '.') return 0;
755 case '1' : case '2' : case '3' : case '4' : case '5' :
756 case '6' : case '7' : case '8' : case '9' : case '0' :
766 if (c == '.') return 0;
771 guint oid_string2subid(const char* str, guint32** subids_p) {
774 guint32* subids_overflow;
775 guint n = check_num_oid(str);
777 * we cannot handle sub-ids greater than 32bytes
778 * keep a pilot subid of 64 bytes to check the limit
782 D(6,("oid_string2subid: str='%s'",str));
789 *subids_p = subids = ep_alloc0(sizeof(guint32)*n);
790 subids_overflow = subids + n;
796 case '1' : case '2' : case '3' : case '4' : case '5' :
797 case '6' : case '7' : case '8' : case '9' : case '0' :
801 if( subids >= subids_overflow || subid > 0xffffffff) {
807 *(subids) += *r - '0';
819 guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_p) {
822 gboolean is_first = TRUE;
824 guint32* subid_overflow;
826 * we cannot handle sub-ids greater than 32bytes
827 * have the subid in 64 bytes to be able to check the limit
831 for (i=0; i<oid_len; i++) { if (! (oid_bytes[i] & 0x80 )) n++; }
833 *subids_p = subids = ep_alloc(sizeof(guint32)*n);
834 subid_overflow = subids+n;
836 for (i=0; i<oid_len; i++){
837 guint8 byte = oid_bytes[i];
840 subid |= byte & 0x7F;
849 if (subid >= 40) { subid0++; subid-=40; }
850 if (subid >= 40) { subid0++; subid-=40; }
857 if( subids >= subid_overflow || subid > 0xffffffff) {
862 *subids++ = (guint32)subid;
869 oid_info_t* oid_get(guint len, guint32* subids, guint* matched, guint* left) {
870 oid_info_t* curr_oid = &oid_root;
873 if(!(subids && *subids <= 2)) {
879 for( i=0; i < len; i++) {
880 oid_info_t* next_oid = emem_tree_lookup32(curr_oid->children,subids[i]);
894 oid_info_t* oid_get_from_encoded(const guint8 *bytes, gint byteslen, guint32** subids_p, guint* matched_p, guint* left_p) {
895 guint subids_len = oid_encoded2subid(bytes, byteslen, subids_p);
896 return oid_get(subids_len, *subids_p, matched_p, left_p);
899 oid_info_t* oid_get_from_string(const gchar *oid_str, guint32** subids_p, guint* matched, guint* left) {
900 guint subids_len = oid_string2subid(oid_str, subids_p);
901 return oid_get(subids_len, *subids_p, matched, left);
904 const gchar *oid_resolved_from_encoded(const guint8 *oid, gint oid_len) {
906 guint subid_oid_length = oid_encoded2subid(oid, oid_len, &subid_oid);
908 return oid_resolved(subid_oid_length, subid_oid);
912 guint oid_subid2encoded(guint subids_len, guint32* subids, guint8** bytes_p) {
919 if ( !subids || subids_len <= 0) {
924 subid = (subids[0] * 40) + subids[1];
928 if (subid <= 0x0000007F) {
930 } else if (subid <= 0x00003FFF ) {
932 } else if (subid <= 0x001FFFFF ) {
934 } else if (subid <= 0x0FFFFFFF ) {
941 } while ( i++ < subids_len );
943 *bytes_p = b = bytes = ep_alloc(bytelen);
945 subid = (subids[0] * 40) + subids[1];
951 if ((subid <= 0x0000007F )) len = 1;
952 else if ((subid <= 0x00003FFF )) len = 2;
953 else if ((subid <= 0x001FFFFF )) len = 3;
954 else if ((subid <= 0x0FFFFFFF )) len = 4;
958 default: *bytes_p=NULL; return 0;
959 case 5: *(b++) = ((subid & 0xF0000000) << 28) | 0x80;
960 case 4: *(b++) = ((subid & 0x0FE00000 ) >> 21) | 0x80;
961 case 3: *(b++) = ((subid & 0x001FC000 ) >> 14) | 0x80;
962 case 2: *(b++) = ((subid & 0x00003F10 ) >> 7) | 0x80;
963 case 1: *(b++) = subid & 0x0000007F ; break;
967 } while ( i++ < subids_len);
972 const gchar* oid_encoded2string(const guint8* encoded, guint len) {
974 guint subids_len = oid_encoded2subid(encoded, len, &subids);
977 return oid_subid2string(subids,subids_len);
985 guint oid_string2encoded(const char *oid_str, guint8 **bytes) {
990 if ( ( subids_len = oid_string2subid(oid_str, &subids) )
992 ( byteslen = oid_subid2encoded(subids_len, subids, bytes) ) ) {
998 char* oid2str(oid_info_t* oid, guint32* subids, guint len, guint left) {
1002 return ep_strdup_printf("%s.%s",oid->name,oid_subid2string(subids+(len-left),left));
1006 const gchar *oid_resolved_from_string(const gchar *oid_str) {
1008 guint subid_oid_length = oid_string2subid(oid_str, &subid_oid);
1010 return oid_resolved(subid_oid_length, subid_oid);
1013 const gchar *oid_resolved(guint32 num_subids, guint32* subids) {
1018 if(! (subids && *subids <= 2 ))
1019 return "*** Malformed OID ***";
1021 oid = oid_get(num_subids, subids, &matched, &left);
1023 while (! oid->name ) {
1024 if (!(oid = oid->parent)) {
1025 return oid_subid2string(subids,num_subids);
1032 return ep_strdup_printf("%s.%s",
1033 oid->name ? oid->name : oid_subid2string(subids,matched),
1034 oid_subid2string(&(subids[matched]),left));
1036 return oid->name ? oid->name : oid_subid2string(subids,matched);
1040 extern void oid_both(guint oid_len, guint32 *subids, char** resolved_p, char** numeric_p) {
1041 *resolved_p = (void*)oid_resolved(oid_len,subids);
1042 *numeric_p = (void*)oid_subid2string(subids,oid_len);
1045 extern void oid_both_from_encoded(const guint8 *oid, gint oid_len, char** resolved_p, char** numeric_p) {
1047 guint subids_len = oid_encoded2subid(oid, oid_len, &subids);
1048 *resolved_p = (void*)oid_resolved(subids_len,subids);
1049 *numeric_p = (void*)oid_subid2string(subids,subids_len);
1052 extern void oid_both_from_string(const gchar *oid_str, char** resolved_p, char** numeric_p) {
1054 guint subids_len = oid_string2subid(oid_str, &subids);
1055 *resolved_p = (void*)oid_resolved(subids_len,subids);
1056 *numeric_p = (void*)oid_subid2string(subids,subids_len);
1060 * Fetch the default OID path.
1063 oid_get_default_mib_path(void) {
1070 path_str = g_string_new("");
1072 #define PATH_SEPARATOR ";"
1073 path = get_datafile_path("snmp\\mibs");
1074 g_string_sprintfa(path_str, "%s;", path);
1077 path = get_persconffile_path("snmp\\mibs", FALSE, FALSE);
1078 g_string_sprintfa(path_str, "%s", path);
1081 #define PATH_SEPARATOR ":"
1082 path = smiGetPath();
1083 g_string_sprintfa(path_str, "%s", path);
1087 for(i=0;i<num_smi_paths;i++) {
1088 if (!( smi_paths[i].name && *smi_paths[i].name))
1091 g_string_sprintfa(path_str,PATH_SEPARATOR "%s",smi_paths[i].name);
1094 path_ret = path_str->str;
1095 g_string_free(path_str, FALSE);
1097 #else /* HAVE_LIBSMI */
1098 return g_strdup("");
1103 char* oid_test_a2b(guint32 num_subids, guint32* subids) {
1108 const char* sub2str = oid_subid2string(subids, num_subids);
1109 guint sub2enc_len = oid_subid2encoded(num_subids, subids,&sub2enc);
1110 guint enc2sub_len = oid_encoded2subid(sub2enc, sub2enc_len, &enc2sub);
1111 const char* enc2str = oid_encoded2string(sub2enc, sub2enc_len);
1112 guint str2enc_len = oid_string2encoded(sub2str,&str2enc);
1113 guint str2sub_len = oid_string2subid(sub2str,&str2sub);
1115 return ep_strdup_printf(
1116 "oid_subid2string=%s \n"
1117 "oid_subid2encoded=[%d]%s \n"
1118 "oid_encoded2subid=%s \n "
1119 "oid_encoded2string=%s \n"
1120 "oid_string2encoded=[%d]%s \n"
1121 "oid_string2subid=%s \n "
1123 ,sub2enc_len,bytestring_to_str(sub2enc, sub2enc_len, ':')
1124 ,enc2sub ? oid_subid2string(enc2sub,enc2sub_len) : "-"
1126 ,str2enc_len,bytestring_to_str(str2enc, str2enc_len, ':')
1127 ,str2sub ? oid_subid2string(str2sub,str2sub_len) : "-"
1131 void add_oid_debug_subtree(oid_info_t* oid_info, proto_tree *tree) {
1132 static const char* oid_kinds[] = { "Unknown", "Node", "Scalar", "Table", "Row", "Column", "Notification", "Group", "Compliance", "Capabilities"};
1133 static const char* key_types[] = {"OID_KEY_TYPE_WRONG","OID_KEY_TYPE_INTEGER",
1134 "OID_KEY_TYPE_FIXED_STRING","OID_KEY_TYPE_FIXED_BYTES","OID_KEY_TYPE_STRING",
1135 "OID_KEY_TYPE_BYTES","OID_KEY_TYPE_NSAP","OID_KEY_TYPE_OID","OID_KEY_TYPE_IPADDR"};
1136 proto_item* pi = proto_tree_add_text(tree,NULL,0,0,
1137 "OidInfo: Name='%s' sub-id=%u kind=%s hfid=%d",
1138 oid_info->name ? oid_info->name : "",
1140 oid_info->kind <= OID_KIND_CAPABILITIES ? oid_kinds[oid_info->kind] : "BROKEN",
1141 oid_info->value_hfid);
1142 proto_tree* pt = proto_item_add_subtree(pi,0);
1145 for(key = oid_info->key; key; key = key->next) {
1146 proto_tree_add_text(pt,NULL,0,0,
1147 "Key: name='%s' num_subids=%d type=%s",
1149 key->key_type <= OID_KEY_TYPE_IPADDR ? key_types[key->key_type] : "BROKEN"
1153 if (oid_info->parent) {
1154 pi = proto_tree_add_text(pt,NULL,0,0,"Parent:");
1155 pt = proto_item_add_subtree(pi,0);
1156 add_oid_debug_subtree(oid_info->parent, pt);
1167 * indent-tabs-mode: tabs
1170 * ex: set shiftwidth=8 tabstop=8 noexpandtab
1171 * :indentSize=8:tabSize=8:noTabs=false: