2 * Routines for OBJECT IDENTIFIER operations
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.
40 #include "report_err.h"
41 #include "filesystem.h"
42 #include "dissectors/packet-ber.h"
48 #define D(level,args) do if (debuglevel >= level) { printf args; printf("\n"); fflush(stdout); } while(0)
52 static int debuglevel = 0;
54 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, OID_KEY_TYPE_INTEGER, 1};
55 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, OID_KEY_TYPE_WRONG, 0};
56 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, OID_KEY_TYPE_OID, 0};
57 static const oid_value_type_t ipv4_type = { FT_IPv4, BASE_NONE, BER_CLASS_APP, 0, 4, 4, OID_KEY_TYPE_IPADDR, OID_KEY_TYPE_IPADDR, 4};
58 static const oid_value_type_t counter32_type = { FT_UINT32, BASE_DEC, BER_CLASS_APP, 1, 1, 4, OID_KEY_TYPE_INTEGER, OID_KEY_TYPE_INTEGER, 1};
59 static const oid_value_type_t unsigned32_type = { FT_UINT32, BASE_DEC, BER_CLASS_APP, 2, 1, 4, OID_KEY_TYPE_INTEGER, OID_KEY_TYPE_INTEGER, 1};
60 static const oid_value_type_t timeticks_type = { FT_UINT32, BASE_DEC, BER_CLASS_APP, 3, 1, 4, OID_KEY_TYPE_INTEGER, OID_KEY_TYPE_INTEGER, 1};
61 static const oid_value_type_t opaque_type = { FT_BYTES, BASE_NONE, BER_CLASS_APP, 4, 1, 4, OID_KEY_TYPE_BYTES, OID_KEY_TYPE_WRONG, 0};
62 static const oid_value_type_t nsap_type = { FT_BYTES, BASE_NONE, BER_CLASS_APP, 5, 8, 8, OID_KEY_TYPE_NSAP, OID_KEY_TYPE_NSAP, 0};
63 static const oid_value_type_t counter64_type = { FT_UINT64, BASE_NONE, BER_CLASS_APP, 6, 8, 8, OID_KEY_TYPE_INTEGER, OID_KEY_TYPE_INTEGER, 1};
64 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, OID_KEY_TYPE_FIXED_BYTES, 16};
65 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, OID_KEY_TYPE_WRONG, 0};
66 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, OID_KEY_TYPE_WRONG, 0};
67 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, OID_KEY_TYPE_FIXED_BYTES, 6};
68 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, OID_KEY_TYPE_WRONG, 0};
69 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};
71 static oid_info_t oid_root = { 0, NULL, OID_KIND_UNKNOWN, NULL, &unknown_type, -2, NULL, NULL, NULL};
72 static emem_tree_t* oids_by_name = NULL;
74 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) {
76 oid_info_t* c = &oid_root;
81 oid_info_t* n = emem_tree_lookup32(c->children,subids[i]);
86 n->name = g_strdup(name);
89 if (! n->value_type) {
96 n = g_malloc(sizeof(oid_info_t));
99 n->children = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_children");
105 emem_tree_insert32(c->children,n->subid,n);
108 n->name = g_strdup(name);
109 n->value_type = type;
113 n->name = g_strdup(name);
114 n->value_type = NULL;
115 n->kind = OID_KIND_UNKNOWN;
121 g_assert_not_reached();
125 extern void oid_add(char* name, guint oid_len, guint32 *subids) {
126 add_oid(name,OID_KIND_UNKNOWN,&unknown_type,NULL,oid_len,subids);
130 typedef struct smi_module_t {
134 static smi_module_t* smi_paths = NULL;
135 static guint num_smi_paths = 0;
136 static uat_t* smi_paths_uat = NULL;
138 static smi_module_t* smi_modules = NULL;
139 static guint num_smi_modules = 0;
140 static uat_t* smi_modules_uat = NULL;
142 UAT_CSTRING_CB_DEF(smi_mod,name,smi_module_t)
144 static void* smi_mod_copy_cb(void* dest, const void* orig, unsigned len _U_) {
145 const smi_module_t* m = orig;
146 smi_module_t* d = dest;
148 d->name = g_strdup(m->name);
153 static void smi_mod_free_cb(void* p) {
155 if (m->name) g_free(m->name);
159 static char* alnumerize(const char* name) {
160 char* s = g_strdup(name);
165 for (;(c = *r); r++) {
166 if (isalnum(c) || c == '_' || c == '-' || c == '.') {
168 } else if (c == ':' && r[1] == ':') {
178 const oid_value_type_t* get_typedata(SmiType* smiType) {
179 static const struct _type_mapping_t {
182 const oid_value_type_t* type;
184 {"IpAddress", SMI_BASETYPE_UNKNOWN, &ipv4_type},
185 {"InetAddressIPv4",SMI_BASETYPE_UNKNOWN,&ipv4_type},
186 {"InetAddressIPv6",SMI_BASETYPE_UNKNOWN,&ipv6_type},
187 {"NetworkAddress",SMI_BASETYPE_UNKNOWN,&ipv4_type},
188 {"MacAddress",SMI_BASETYPE_UNKNOWN,ðer_type},
189 {"TimeTicks",SMI_BASETYPE_UNKNOWN,&timeticks_type},
190 {"Ipv6Address",SMI_BASETYPE_UNKNOWN,&ipv6_type},
191 {"TimeStamp",SMI_BASETYPE_UNKNOWN,&integer_type},
192 {"DisplayString",SMI_BASETYPE_UNKNOWN,&string_type},
193 {"DateAndTime",SMI_BASETYPE_UNKNOWN,&string_type},
194 {"Counter",SMI_BASETYPE_UNKNOWN,&counter32_type},
195 {"Counter32",SMI_BASETYPE_UNKNOWN,&counter32_type},
196 {"Unsigned32",SMI_BASETYPE_UNKNOWN,&unsigned32_type},
197 {"Gauge",SMI_BASETYPE_UNKNOWN,&unsigned32_type},
198 {"Gauge32",SMI_BASETYPE_UNKNOWN,&unsigned32_type},
199 {"NsapAddress",SMI_BASETYPE_UNKNOWN,&nsap_type},
200 {"i32",SMI_BASETYPE_INTEGER32,&integer_type},
201 {"octets",SMI_BASETYPE_OCTETSTRING,&bytes_type},
202 {"oid",SMI_BASETYPE_OBJECTIDENTIFIER,&oid_type},
203 {"u32",SMI_BASETYPE_UNSIGNED32,&unsigned32_type},
204 {"u64",SMI_BASETYPE_UNSIGNED64,&counter64_type},
205 {"f32",SMI_BASETYPE_FLOAT32,&float_type},
206 {"f64",SMI_BASETYPE_FLOAT64,&double_type},
207 {"f128",SMI_BASETYPE_FLOAT128,&bytes_type},
208 {"enum",SMI_BASETYPE_ENUM,&integer_type},
209 {"bits",SMI_BASETYPE_BITS,&bytes_type},
210 {"unk",SMI_BASETYPE_UNKNOWN,&unknown_type},
213 const struct _type_mapping_t* t;
214 SmiType* sT = smiType;
216 if (!smiType) return NULL;
219 for (t = types; t->type ; t++ ) {
220 const char* name = smiRenderType(sT, SMI_RENDER_NAME);
221 if (name && t->name && g_str_equal(name, t->name )) {
225 } while(( sT = smiGetParentType(sT) ));
227 for (t = types; t->type ; t++ ) {
228 if(smiType->basetype == t->base) {
233 return &unknown_type;
236 static inline oid_kind_t smikind(SmiNode* sN, oid_key_t** key_p) {
239 switch(sN->nodekind) {
240 case SMI_NODEKIND_ROW: {
242 oid_key_t* kl = NULL;
243 const oid_value_type_t* typedata = NULL;
245 switch (sN->indexkind) {
246 case SMI_INDEX_INDEX:
248 case SMI_INDEX_AUGMENT:
249 case SMI_INDEX_REORDER:
250 case SMI_INDEX_SPARSE:
251 case SMI_INDEX_UNKNOWN:
252 case SMI_INDEX_EXPAND:
253 return OID_KIND_UNKNOWN;
258 for (sE = smiGetFirstElement(sN); sE; sE = smiGetNextElement(sE)) {
259 SmiNode* elNode = smiGetElementNode(sE) ;
260 SmiType* elType = smiGetNodeType(elNode);
263 typedata = get_typedata(elType);
265 k = g_malloc(sizeof(oid_key_t));
267 k->name = g_strdup_printf("%s.%s",
268 smiRenderOID(sN->oidlen, sN->oid, SMI_RENDER_QUALIFIED),
269 smiRenderOID(elNode->oidlen, elNode->oid, SMI_RENDER_NAME));
271 k->ft_type = typedata ? typedata->ft_type : FT_BYTES;
272 k->display = typedata ? typedata->display : BASE_NONE;
277 k->key_type = typedata->keytype;
278 k->num_subids = typedata->keysize;
281 switch (elType->basetype) {
282 case SMI_BASETYPE_BITS:
283 case SMI_BASETYPE_OCTETSTRING:
284 k->key_type = OID_KEY_TYPE_BYTES;
285 /* XXX find out how to fetch k->num_subids */
288 case SMI_BASETYPE_ENUM:
289 case SMI_BASETYPE_OBJECTIDENTIFIER:
290 case SMI_BASETYPE_INTEGER32:
291 case SMI_BASETYPE_UNSIGNED32:
292 case SMI_BASETYPE_INTEGER64:
293 case SMI_BASETYPE_UNSIGNED64:
294 k->key_type = OID_KEY_TYPE_INTEGER;
298 k->key_type = OID_KEY_TYPE_WRONG;
303 k->key_type = OID_KEY_TYPE_WRONG;
309 if (!*key_p) *key_p = k;
310 if (kl) kl->next = k;
317 kl->key_type = typedata->keytype_implicit;
319 /* XXX: what should we do ? */
320 kl->key_type = kl->key_type;
326 case SMI_NODEKIND_NODE: return OID_KIND_NODE;
327 case SMI_NODEKIND_SCALAR: return OID_KIND_SCALAR;
328 case SMI_NODEKIND_TABLE: return OID_KIND_TABLE;
329 case SMI_NODEKIND_COLUMN: return OID_KIND_COLUMN;
330 case SMI_NODEKIND_NOTIFICATION: return OID_KIND_NOTIFICATION;
331 case SMI_NODEKIND_GROUP: return OID_KIND_GROUP;
332 case SMI_NODEKIND_COMPLIANCE: return OID_KIND_COMPLIANCE;
333 case SMI_NODEKIND_CAPABILITIES: return OID_KIND_CAPABILITIES;
334 default: return OID_KIND_UNKNOWN;
338 #define IS_ENUMABLE(ft) ( (ft == FT_UINT8) || (ft == FT_UINT16) || (ft == FT_UINT24) || (ft == FT_UINT32) \
339 || (ft == FT_INT8) || (ft == FT_INT16) || (ft == FT_INT24) || (ft == FT_INT32) \
340 || (ft == FT_UINT64) || (ft == FT_INT64) )
342 void register_mibs(void) {
343 SmiModule *smiModule;
347 module_t* mibs_module;
348 GArray* hfa = g_array_new(FALSE,TRUE,sizeof(hf_register_info));
349 GArray* etta = g_array_new(FALSE,TRUE,sizeof(gint*));
350 static uat_field_t smi_fields[] = {
351 UAT_FLD_CSTRING(smi_mod,name,"The module's name"),
354 static uat_field_t smi_paths_fields[] = {
355 UAT_FLD_CSTRING(smi_mod,name,"The directory name"),
358 char* smi_load_error = NULL;
360 char* debug_env = getenv("WIRESHARK_DEBUG_MIBS");
362 debuglevel = debug_env ? strtoul(debug_env,NULL,10) : 0;
364 smi_modules_uat = uat_new("SMI Modules",
365 sizeof(smi_module_t),
367 (void**)&smi_modules,
376 smi_paths_uat = uat_new("SMI Paths",
377 sizeof(smi_module_t),
389 uat_load(smi_modules_uat, &smi_load_error);
391 if (smi_load_error) {
392 report_failure("Error Loading SMI Modules Table: %s",smi_load_error);
396 uat_load(smi_paths_uat, &smi_load_error);
398 if (smi_load_error) {
399 report_failure("Error Loading SMI Paths Table: %s",smi_load_error);
403 path_str = g_string_new(get_datafile_path("mibs"));
404 g_string_sprintfa(path_str,":%s",get_persconffile_path("mibs", FALSE));
406 for(i=0;i<num_smi_paths;i++) {
407 if (!( smi_paths[i].name && *smi_paths[i].name))
410 g_string_sprintfa(path_str,":%s",smi_paths[i].name);
413 D(1,("SMI Path: '%s'",path_str->str));
417 smiSetPath(path_str->str);
419 g_string_free(path_str,TRUE);
421 for(i=0;i<num_smi_modules;i++) {
422 if (!smi_modules[i].name) continue;
425 if (smiIsLoaded(smi_modules[i].name)) {
428 char* mod_name = smiLoadModule(smi_modules[i].name);
430 D(2,("Loaded: '%s'[%d] as %s",smi_modules[i].name,i,mod_name ));
432 D(1,("Failed to load: '%s'[%d]",smi_modules[i].name,i));
436 for (smiModule = smiGetFirstModule();
438 smiModule = smiGetNextModule(smiModule)) {
440 D(3,("\tModule: %s", smiModule->name));
442 for (smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
444 smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_ANY)) {
446 SmiType* smiType = smiGetNodeType(smiNode);
447 const oid_value_type_t* typedata = get_typedata(smiType);
449 oid_kind_t kind = smikind(smiNode,&key);
450 oid_info_t* oid_data = add_oid(smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_QUALIFIED),
458 D(4,("\t\tNode: kind=%d oid=%s name=%s ",
459 oid_data->kind, oid_subid2string(smiNode->oid, smiNode->oidlen), oid_data->name ));
461 if ( typedata && oid_data->value_hfid == -2 ) {
462 SmiNamedNumber* smiEnum;
463 hf_register_info hf = { &(oid_data->value_hfid), {
465 alnumerize(oid_data->name),
470 g_strdup(smiRenderOID(smiNode->oidlen, smiNode->oid, SMI_RENDER_ALL)),
473 oid_data->value_hfid = -1;
475 if ( IS_ENUMABLE(hf.hfinfo.type) && (smiEnum = smiGetFirstNamedNumber(smiType))) {
476 GArray* vals = g_array_new(TRUE,TRUE,sizeof(value_string));
478 for(;smiEnum; smiEnum = smiGetNextNamedNumber(smiEnum)) {
480 value_string val = {smiEnum->value.value.integer32,g_strdup(smiEnum->name)};
481 g_array_append_val(vals,val);
485 hf.hfinfo.strings = VALS(vals->data);
486 g_array_free(vals,FALSE);
488 #if 0 /* packet-snmp does not hanldle bits yet */
489 } else if (smiType->basetype == SMI_BASETYPE_BITS && ( smiEnum = smiGetFirstNamedNumber(smiType) )) {
491 oid_bits_info_t* bits = g_malloc(sizeof(oid_bits_info_t));
492 gint* ettp = &(bits->ett);
497 g_array_append_val(etta,ettp);
499 for(;smiEnum; smiEnum = smiGetNextNamedNumber(smiEnum), bits->num++);
501 bits->data = g_malloc(sizeof(struct _oid_bit_t)*bits->num);
503 for(smiEnum = smiGetFirstNamedNumber(smiType),n=0;
505 smiEnum = smiGetNextNamedNumber(smiEnum),n++) {
506 guint mask = 1 << (smiEnum->value.value.integer32 % 8);
507 char* base = alnumerize(oid_data->name);
508 char* ext = alnumerize(smiEnum->name);
509 hf_register_info hf2 = { &(bits->data[n].hfid), { NULL, NULL, FT_UINT8, BASE_HEX, NULL, mask, "", HFILL }};
511 bits->data[n].hfid = -1;
512 bits->data[n].offset = smiEnum->value.value.integer32 / 8;
514 hf2.hfinfo.name = g_strdup_printf("%s:%s",oid_data->name,smiEnum->name);
515 hf2.hfinfo.abbrev = g_strdup_printf("%s.%s",base,ext);
519 g_array_append_val(hfa,hf2);
521 #endif /* packet-snmp does not use this yet */
522 g_array_append_val(hfa,hf);
525 if ((key = oid_data->key)) {
526 for(; key; key = key->next) {
527 hf_register_info hf = { &(key->hfid), {
529 alnumerize(key->name),
537 D(5,("\t\t\tIndex: name=%s subids=%d key_type=%d",
538 key->name, key->num_subids, key->key_type ));
540 if (key->hfid == -2) {
541 g_array_append_val(hfa,hf);
544 g_free((void*)hf.hfinfo.abbrev);
552 proto_mibs = proto_register_protocol("MIBs", "MIBS", "mibs");
554 proto_register_field_array(proto_mibs, (hf_register_info*)hfa->data, hfa->len);
555 mibs_module = prefs_register_protocol(proto_mibs, NULL);
557 prefs_register_uat_preference(mibs_module, "smi_paths",
559 "List of directories where MIBs are to be looked for",
562 prefs_register_uat_preference(mibs_module, "smi_modules",
564 "List of MIB modules to be loaded",
567 proto_register_subtree_array((gint**)etta->data, etta->len);
570 g_array_free(etta,TRUE);
571 g_array_free(hfa,FALSE);
576 void oid_init(void) {
577 oid_root.children = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_root");
578 oids_by_name = pe_tree_create(EMEM_TREE_TYPE_RED_BLACK,"oid_names");
585 const char* oid_subid2string(guint32* subids, guint len) {
586 char* s = ep_alloc0(len*11);
590 w += sprintf(w,"%u.",*subids++);
593 if (w!=s) *(w-1) = '\0'; else *(w) = '\0';
598 guint check_num_oid(const char* str) {
603 if (*r == '.') return 0;
609 if (c == '.') return 0;
610 case '1' : case '2' : case '3' : case '4' : case '5' :
611 case '6' : case '7' : case '8' : case '9' : case '0' :
621 if (c == '.') return 0;
626 guint oid_string2subid(const char* str, guint32** subids_p) {
629 guint n = check_num_oid(str);
636 *subids_p = subids = ep_alloc_array(guint32,n);
642 case '1' : case '2' : case '3' : case '4' : case '5' :
643 case '6' : case '7' : case '8' : case '9' : case '0' :
645 *(subids) += *r - '0';
657 guint oid_encoded2subid(const guint8 *oid_bytes, gint oid_len, guint32** subids_p) {
661 gboolean is_first = TRUE;
664 for (i=0; i<oid_len; i++) { if (! (oid_bytes[i] & 0x80 )) n++; }
666 *subids_p = subids = ep_alloc(sizeof(guint32)*n);
668 for (i=0; i<oid_len; i++){
669 guint8 byte = oid_bytes[i];
672 subid |= byte & 0x7F;
681 if (subid >= 40) { subid0++; subid-=40; }
682 if (subid >= 40) { subid0++; subid-=40; }
696 oid_info_t* oid_get(guint len, guint32* subids, guint* matched, guint* left) {
697 oid_info_t* curr_oid = &oid_root;
700 for( i=0; i < len; i++) {
701 oid_info_t* next_oid = emem_tree_lookup32(curr_oid->children,subids[i]);
715 oid_info_t* oid_get_from_encoded(const guint8 *bytes, gint byteslen, guint32** subids_p, guint* matched_p, guint* left_p) {
716 return oid_get(oid_encoded2subid(bytes, byteslen, subids_p), *subids_p, matched_p, left_p);
719 oid_info_t* oid_get_from_string(const gchar *oid_str, guint32** subids_p, guint* matched, guint* left) {
720 return oid_get(oid_string2subid(oid_str, subids_p), *subids_p, matched, left);
723 const gchar *oid_resolved_from_encoded(const guint8 *oid, gint oid_len) {
725 guint subid_oid_length = oid_encoded2subid(oid, oid_len, &subid_oid);
728 oid_info_t* curr_oid = oid_get(subid_oid_length, subid_oid, &matched, &left);
730 if (matched == subid_oid_length) {
731 return curr_oid->name;
733 return ep_strdup_printf("%s.%s",
735 oid_subid2string(&(subid_oid[matched]),left) );
741 guint oid_subid2encoded(guint subids_len, guint32* subids, guint8** bytes_p) {
748 if (subids_len < 2) {
753 subid = (subids[0] * 40) + subids[1];
757 if (subid <= 0x0000007F) {
759 } else if (subid <= 0x00003FFF ) {
761 } else if (subid <= 0x001FFFFF ) {
763 } else if (subid <= 0x0FFFFFFF ) {
770 } while ( i++ < subids_len );
772 *bytes_p = b = bytes = ep_alloc(bytelen);
774 subid = (subids[0] * 40) + subids[1];
780 if ((subid <= 0x0000007F )) len = 1;
781 else if ((subid <= 0x00003FFF )) len = 2;
782 else if ((subid <= 0x001FFFFF )) len = 3;
783 else if ((subid <= 0x0FFFFFFF )) len = 4;
787 default: DISSECTOR_ASSERT_NOT_REACHED(); break;
788 case 5: *(b++) = ((subid & 0xF0000000) << 28) | 0x80;
789 case 4: *(b++) = ((subid & 0x0FE00000 ) >> 21) | 0x80;
790 case 3: *(b++) = ((subid & 0x001FC000 ) >> 14) | 0x80;
791 case 2: *(b++) = ((subid & 0x00003F10 ) >> 7) | 0x80;
792 case 1: *(b++) = subid & 0x0000007F ; break;
796 } while ( i++ < subids_len);
801 const gchar* oid_encoded2string(const guint8* encoded, guint len) {
803 guint subids_len = oid_encoded2subid(encoded, len, &subids);
806 return oid_subid2string(subids,subids_len);
814 guint oid_string2encoded(const char *oid_str, guint8 **bytes) {
819 if ( ( subids_len = oid_string2subid(oid_str, &subids) )
821 ( byteslen = oid_subid2encoded(subids_len, subids, bytes) ) ) {
827 char* oid2str(oid_info_t* oid, guint32* subids, guint len, guint left) {
831 return ep_strdup_printf("%s.%s",oid->name,oid_subid2string(subids+(len-left),left));
835 const gchar *oid_resolved_from_string(const gchar *oid_str) {
837 guint num_subids = oid_string2subid(oid_str, &subids);
842 oid_info_t* oid = oid_get(num_subids, subids, &matched, &left);
843 return oid2str(oid, subids, num_subids, left);
845 return emem_tree_lookup_string(oids_by_name, oid_str);
849 extern char* oid_test_a2b(guint32 num_subids, guint32* subids);
850 char* oid_test_a2b(guint32 num_subids, guint32* subids) {
855 const char* sub2str = oid_subid2string(subids, num_subids);
856 guint sub2enc_len = oid_subid2encoded(num_subids, subids,&sub2enc);
857 guint enc2sub_len = oid_encoded2subid(sub2enc, sub2enc_len, &enc2sub);
858 const char* enc2str = oid_encoded2string(sub2enc, sub2enc_len);
859 guint str2enc_len = oid_string2encoded(sub2str,&str2enc);
860 guint str2sub_len = oid_string2subid(sub2str,&str2sub);
862 return ep_strdup_printf(
863 "oid_subid2string=%s \n"
864 "oid_subid2encoded=[%d]%s \n"
865 "oid_encoded2subid=%s \n "
866 "oid_encoded2string=%s \n"
867 "oid_string2encoded=[%d]%s \n"
868 "oid_string2subid=%s \n "
870 ,sub2enc_len,bytestring_to_str(sub2enc, sub2enc_len, ':')
871 ,enc2sub ? oid_subid2string(enc2sub,enc2sub_len) : "-"
873 ,str2enc_len,bytestring_to_str(str2enc, str2enc_len, ':')
874 ,str2sub ? oid_subid2string(str2sub,str2sub_len) : "-"
878 const gchar *oid_resolved(guint32 num_subids, guint32* subids) {
881 oid_info_t* oid = oid_get(num_subids, subids, &matched, &left);
883 while (! oid->name ) {
884 if (!(oid = oid->parent)) {
885 return oid_subid2string(subids,num_subids);
892 return ep_strdup_printf("%s.%s",
894 oid_subid2string(&(subids[matched]),left));