Mercurial > flash_v2
comparison packages/net/snmp/lib/current/src/mib.c @ 103:95f3e12a6327 ecos-sw-2000-06-23
Merge from eCos master repository on 2000-06-23-16:41:10-BST
| author | jlarmour |
|---|---|
| date | Fri, 23 Jun 2000 17:06:31 +0000 |
| parents | |
| children | e0c0827131d1 |
comparison
equal
deleted
inserted
replaced
| 102:6409b6d94dd7 | 103:95f3e12a6327 |
|---|---|
| 1 //========================================================================== | |
| 2 // | |
| 3 // ./lib/current/src/mib.c | |
| 4 // | |
| 5 // | |
| 6 //========================================================================== | |
| 7 //####COPYRIGHTBEGIN#### | |
| 8 // | |
| 9 // ------------------------------------------- | |
| 10 // The contents of this file are subject to the Red Hat eCos Public License | |
| 11 // Version 1.1 (the "License"); you may not use this file except in | |
| 12 // compliance with the License. You may obtain a copy of the License at | |
| 13 // http://www.redhat.com/ | |
| 14 // | |
| 15 // Software distributed under the License is distributed on an "AS IS" | |
| 16 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the | |
| 17 // License for the specific language governing rights and limitations under | |
| 18 // the License. | |
| 19 // | |
| 20 // The Original Code is eCos - Embedded Configurable Operating System, | |
| 21 // released September 30, 1998. | |
| 22 // | |
| 23 // The Initial Developer of the Original Code is Red Hat. | |
| 24 // Portions created by Red Hat are | |
| 25 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. | |
| 26 // All Rights Reserved. | |
| 27 // ------------------------------------------- | |
| 28 // | |
| 29 //####COPYRIGHTEND#### | |
| 30 //####UCDSNMPCOPYRIGHTBEGIN#### | |
| 31 // | |
| 32 // ------------------------------------------- | |
| 33 // | |
| 34 // Portions of this software may have been derived from the UCD-SNMP | |
| 35 // project, <http://ucd-snmp.ucdavis.edu/> from the University of | |
| 36 // California at Davis, which was originally based on the Carnegie Mellon | |
| 37 // University SNMP implementation. Portions of this software are therefore | |
| 38 // covered by the appropriate copyright disclaimers included herein. | |
| 39 // | |
| 40 // The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" | |
| 41 // ------------------------------------------- | |
| 42 // | |
| 43 //####UCDSNMPCOPYRIGHTEND#### | |
| 44 //========================================================================== | |
| 45 //#####DESCRIPTIONBEGIN#### | |
| 46 // | |
| 47 // Author(s): hmt | |
| 48 // Contributors: hmt | |
| 49 // Date: 2000-05-30 | |
| 50 // Purpose: Port of UCD-SNMP distribution to eCos. | |
| 51 // Description: | |
| 52 // | |
| 53 // | |
| 54 //####DESCRIPTIONEND#### | |
| 55 // | |
| 56 //========================================================================== | |
| 57 /******************************************************************** | |
| 58 Copyright 1989, 1991, 1992 by Carnegie Mellon University | |
| 59 | |
| 60 Derivative Work - | |
| 61 Copyright 1996, 1998, 1999, 2000 The Regents of the University of California | |
| 62 | |
| 63 All Rights Reserved | |
| 64 | |
| 65 Permission to use, copy, modify and distribute this software and its | |
| 66 documentation for any purpose and without fee is hereby granted, | |
| 67 provided that the above copyright notice appears in all copies and | |
| 68 that both that copyright notice and this permission notice appear in | |
| 69 supporting documentation, and that the name of CMU and The Regents of | |
| 70 the University of California not be used in advertising or publicity | |
| 71 pertaining to distribution of the software without specific written | |
| 72 permission. | |
| 73 | |
| 74 CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL | |
| 75 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED | |
| 76 WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR | |
| 77 THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, | |
| 78 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING | |
| 79 FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF | |
| 80 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
| 81 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
| 82 *********************************************************************/ | |
| 83 /* | |
| 84 * mib.c | |
| 85 * | |
| 86 * Update: 1998-07-17 <jhy@gsu.edu> | |
| 87 * Added print_oid_report* functions. | |
| 88 * | |
| 89 */ | |
| 90 /********************************************************************** | |
| 91 Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University | |
| 92 | |
| 93 All Rights Reserved | |
| 94 | |
| 95 Permission to use, copy, modify, and distribute this software and its | |
| 96 documentation for any purpose and without fee is hereby granted, | |
| 97 provided that the above copyright notice appear in all copies and that | |
| 98 both that copyright notice and this permission notice appear in | |
| 99 supporting documentation, and that the name of CMU not be | |
| 100 used in advertising or publicity pertaining to distribution of the | |
| 101 software without specific, written prior permission. | |
| 102 | |
| 103 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | |
| 104 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |
| 105 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | |
| 106 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
| 107 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
| 108 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
| 109 SOFTWARE. | |
| 110 ******************************************************************/ | |
| 111 #include <config.h> | |
| 112 | |
| 113 #include <stdio.h> | |
| 114 #include <ctype.h> | |
| 115 #include <sys/types.h> | |
| 116 #if HAVE_NETINET_IN_H | |
| 117 #include <netinet/in.h> | |
| 118 #endif | |
| 119 #if TIME_WITH_SYS_TIME | |
| 120 # ifdef WIN32 | |
| 121 # include <sys/timeb.h> | |
| 122 # else | |
| 123 # include <sys/time.h> | |
| 124 # endif | |
| 125 # include <time.h> | |
| 126 #else | |
| 127 # if HAVE_SYS_TIME_H | |
| 128 # include <sys/time.h> | |
| 129 # else | |
| 130 # include <time.h> | |
| 131 # endif | |
| 132 #endif | |
| 133 #if HAVE_STRING_H | |
| 134 #include <string.h> | |
| 135 #else | |
| 136 #include <strings.h> | |
| 137 #endif | |
| 138 #if HAVE_STDLIB_H | |
| 139 #include <stdlib.h> | |
| 140 #endif | |
| 141 #if HAVE_SYS_SELECT_H | |
| 142 #include <sys/select.h> | |
| 143 #endif | |
| 144 | |
| 145 #if HAVE_WINSOCK_H | |
| 146 #include <winsock.h> | |
| 147 #endif | |
| 148 | |
| 149 #if HAVE_DMALLOC_H | |
| 150 #include <dmalloc.h> | |
| 151 #endif | |
| 152 | |
| 153 #include "asn1.h" | |
| 154 #include "snmp_api.h" | |
| 155 #include "mib.h" | |
| 156 #include "snmp.h" | |
| 157 #include "snmp_impl.h" | |
| 158 #include "parse.h" | |
| 159 #include "int64.h" | |
| 160 #include "system.h" | |
| 161 #include "read_config.h" | |
| 162 #include "snmp_debug.h" | |
| 163 #include "default_store.h" | |
| 164 | |
| 165 static void sprint_by_type (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 166 static int parse_subtree (struct tree *, const char *, oid *, size_t *); | |
| 167 static struct tree * _sprint_objid(char *buf, oid *objid, size_t objidlen); | |
| 168 static char *uptimeString (u_long, char *); | |
| 169 static void sprint_octet_string (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 170 static void sprint_opaque (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 171 static void sprint_object_identifier (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 172 static void sprint_timeticks (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 173 static void sprint_hinted_integer (char *, long, const char *, const char *); | |
| 174 static void sprint_integer (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 175 static void sprint_uinteger (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 176 static void sprint_gauge (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 177 static void sprint_counter (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 178 static void sprint_networkaddress (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 179 static void sprint_ipaddress (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 180 static void sprint_null (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 181 static void sprint_bitstring (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 182 static void sprint_nsapaddress (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 183 static void sprint_counter64 (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 184 static void sprint_unknowntype (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 185 static void sprint_badtype (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 186 struct tree *_get_symbol(oid *objid, size_t objidlen, struct tree *subtree, char *buf, struct index_list *in_dices, char **end_of_known); | |
| 187 | |
| 188 #ifdef OPAQUE_SPECIAL_TYPES | |
| 189 static void sprint_float (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 190 static void sprint_double (char *, struct variable_list *, struct enum_list *, const char *, const char *); | |
| 191 #endif | |
| 192 void print_tree_node (FILE *f, struct tree *tp); | |
| 193 | |
| 194 /* helper functions for get_module_node */ | |
| 195 int node_to_oid(struct tree *, oid *, size_t *); | |
| 196 static int _add_strings_to_oid(struct tree *, char *, | |
| 197 oid *, size_t *, size_t); | |
| 198 | |
| 199 extern struct tree *tree_head; | |
| 200 | |
| 201 struct tree *Mib; /* Backwards compatibility */ | |
| 202 | |
| 203 oid RFC1213_MIB[] = { 1, 3, 6, 1, 2, 1 }; | |
| 204 static char Standard_Prefix[] = ".1.3.6.1.2.1"; | |
| 205 | |
| 206 /* Set default here as some uses of read_objid require valid pointer. */ | |
| 207 static char *Prefix = &Standard_Prefix[0]; | |
| 208 typedef struct _PrefixList { | |
| 209 const char *str; | |
| 210 int len; | |
| 211 } *PrefixListPtr, PrefixList; | |
| 212 | |
| 213 /* | |
| 214 * Here are the prefix strings. | |
| 215 * Note that the first one finds the value of Prefix or Standard_Prefix. | |
| 216 * Any of these MAY start with period; all will NOT end with period. | |
| 217 * Period is added where needed. See use of Prefix in this module. | |
| 218 */ | |
| 219 PrefixList mib_prefixes[] = { | |
| 220 { &Standard_Prefix[0] }, /* placeholder for Prefix data */ | |
| 221 { ".iso.org.dod.internet.mgmt.mib-2" }, | |
| 222 { ".iso.org.dod.internet.experimental" }, | |
| 223 { ".iso.org.dod.internet.private" }, | |
| 224 { ".iso.org.dod.internet.snmpParties" }, | |
| 225 { ".iso.org.dod.internet.snmpSecrets" }, | |
| 226 { NULL, 0 } /* end of list */ | |
| 227 }; | |
| 228 | |
| 229 static char * | |
| 230 uptimeString(u_long timeticks, | |
| 231 char *buf) | |
| 232 { | |
| 233 int centisecs, seconds, minutes, hours, days; | |
| 234 | |
| 235 centisecs = timeticks % 100; | |
| 236 timeticks /= 100; | |
| 237 days = timeticks / (60 * 60 * 24); | |
| 238 timeticks %= (60 * 60 * 24); | |
| 239 | |
| 240 hours = timeticks / (60 * 60); | |
| 241 timeticks %= (60 * 60); | |
| 242 | |
| 243 minutes = timeticks / 60; | |
| 244 seconds = timeticks % 60; | |
| 245 | |
| 246 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) | |
| 247 sprintf(buf, "%d:%d:%02d:%02d.%02d", | |
| 248 days, hours, minutes, seconds, centisecs); | |
| 249 else { | |
| 250 if (days == 0){ | |
| 251 sprintf(buf, "%d:%02d:%02d.%02d", | |
| 252 hours, minutes, seconds, centisecs); | |
| 253 } else if (days == 1) { | |
| 254 sprintf(buf, "%d day, %d:%02d:%02d.%02d", | |
| 255 days, hours, minutes, seconds, centisecs); | |
| 256 } else { | |
| 257 sprintf(buf, "%d days, %d:%02d:%02d.%02d", | |
| 258 days, hours, minutes, seconds, centisecs); | |
| 259 } | |
| 260 } | |
| 261 return buf; | |
| 262 } | |
| 263 | |
| 264 | |
| 265 | |
| 266 void sprint_hexstring(char *buf, | |
| 267 const u_char *cp, | |
| 268 size_t len) | |
| 269 { | |
| 270 | |
| 271 for(; len >= 16; len -= 16){ | |
| 272 sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X %02X ", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); | |
| 273 buf += strlen(buf); | |
| 274 cp += 8; | |
| 275 sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X %02X", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); | |
| 276 buf += strlen(buf); | |
| 277 if (len > 16) { *buf++ = '\n'; *buf = 0; } | |
| 278 cp += 8; | |
| 279 } | |
| 280 for(; len > 0; len--){ | |
| 281 sprintf(buf, "%02X ", *cp++); | |
| 282 buf += strlen(buf); | |
| 283 } | |
| 284 *buf = '\0'; | |
| 285 } | |
| 286 | |
| 287 void sprint_asciistring(char *buf, | |
| 288 u_char *cp, | |
| 289 size_t len) | |
| 290 { | |
| 291 int x; | |
| 292 | |
| 293 for(x = 0; x < (int)len; x++){ | |
| 294 if (isprint(*cp)){ | |
| 295 *buf++ = *cp++; | |
| 296 } else { | |
| 297 *buf++ = '.'; | |
| 298 cp++; | |
| 299 } | |
| 300 #if 0 | |
| 301 if ((x % 48) == 47) | |
| 302 *buf++ = '\n'; | |
| 303 #endif | |
| 304 } | |
| 305 *buf = '\0'; | |
| 306 } | |
| 307 | |
| 308 | |
| 309 /* | |
| 310 0 | |
| 311 < 4 | |
| 312 hex | |
| 313 | |
| 314 0 "" | |
| 315 < 4 hex Hex: oo oo oo | |
| 316 < 4 "fgh" Hex: oo oo oo | |
| 317 > 4 hex Hex: oo oo oo oo oo oo oo oo | |
| 318 > 4 "this is a test" | |
| 319 | |
| 320 */ | |
| 321 | |
| 322 static void | |
| 323 sprint_octet_string(char *buf, | |
| 324 struct variable_list *var, | |
| 325 struct enum_list *enums, | |
| 326 const char *hint, | |
| 327 const char *units) | |
| 328 { | |
| 329 int hex, x; | |
| 330 u_char *cp; | |
| 331 const char *saved_hint = hint; | |
| 332 char *saved_buf = buf; | |
| 333 | |
| 334 if (var->type != ASN_OCTET_STR){ | |
| 335 sprintf(buf, "Wrong Type (should be OCTET STRING): "); | |
| 336 buf += strlen(buf); | |
| 337 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 338 return; | |
| 339 } | |
| 340 | |
| 341 if (hint) { | |
| 342 int repeat, width = 1; | |
| 343 long value; | |
| 344 char code = 'd', separ = 0, term = 0, ch; | |
| 345 u_char *ecp; | |
| 346 | |
| 347 *buf = 0; | |
| 348 cp = var->val.string; | |
| 349 ecp = cp + var->val_len; | |
| 350 while (cp < ecp) { | |
| 351 repeat = 1; | |
| 352 if (*hint) { | |
| 353 if (*hint == '*') { | |
| 354 repeat = *cp++; | |
| 355 hint++; | |
| 356 } | |
| 357 width = 0; | |
| 358 while ('0' <= *hint && *hint <= '9') | |
| 359 width = width * 10 + *hint++ - '0'; | |
| 360 code = *hint++; | |
| 361 if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9') | |
| 362 && (width != 0 || (ch != 'x' && ch != 'd' && ch != 'o'))) | |
| 363 separ = *hint++; | |
| 364 else separ = 0; | |
| 365 if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9') | |
| 366 && (width != 0 || (ch != 'x' && ch != 'd' && ch != 'o'))) | |
| 367 term = *hint++; | |
| 368 else term = 0; | |
| 369 if (width == 0) width = 1; | |
| 370 } | |
| 371 while (repeat && cp < ecp) { | |
| 372 value = 0; | |
| 373 if (code != 'a') | |
| 374 for (x = 0; x < width; x++) value = value * 256 + *cp++; | |
| 375 switch (code) { | |
| 376 case 'x': | |
| 377 sprintf (buf, "%lx", value); break; | |
| 378 case 'd': | |
| 379 sprintf (buf, "%ld", value); break; | |
| 380 case 'o': | |
| 381 sprintf (buf, "%lo", value); break; | |
| 382 case 'a': | |
| 383 for (x = 0; x < width && cp < ecp; x++) | |
| 384 *buf++ = *cp++; | |
| 385 *buf = 0; | |
| 386 break; | |
| 387 default: | |
| 388 sprintf(saved_buf, "(Bad hint ignored: %s) ", saved_hint); | |
| 389 sprint_octet_string(saved_buf+strlen(saved_buf), | |
| 390 var, enums, NULL, NULL); | |
| 391 return; | |
| 392 } | |
| 393 buf += strlen (buf); | |
| 394 if (cp < ecp && separ) *buf++ = separ; | |
| 395 repeat--; | |
| 396 } | |
| 397 if (term && cp < ecp) *buf++ = term; | |
| 398 } | |
| 399 if (units) sprintf (buf, " %s", units); | |
| 400 return; | |
| 401 } | |
| 402 | |
| 403 hex = 0; | |
| 404 for(cp = var->val.string, x = 0; x < (int)var->val_len; x++, cp++){ | |
| 405 if (!(isprint(*cp) || isspace(*cp))) | |
| 406 hex = 1; | |
| 407 } | |
| 408 if (var->val_len == 0){ | |
| 409 strcpy(buf, "\"\""); | |
| 410 return; | |
| 411 } | |
| 412 if (!hex){ | |
| 413 *buf++ = '"'; | |
| 414 sprint_asciistring(buf, var->val.string, var->val_len); | |
| 415 buf += strlen(buf); | |
| 416 *buf++ = '"'; | |
| 417 *buf = '\0'; | |
| 418 } | |
| 419 if (hex || ((var->val_len <= 4) && !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT))){ | |
| 420 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 421 *buf++ = '"'; | |
| 422 *buf = '\0'; | |
| 423 } else { | |
| 424 sprintf(buf, " Hex: "); | |
| 425 buf += strlen(buf); | |
| 426 } | |
| 427 sprint_hexstring(buf, var->val.string, var->val_len); | |
| 428 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 429 buf += strlen(buf); | |
| 430 *buf++ = '"'; | |
| 431 *buf = '\0'; | |
| 432 } | |
| 433 } | |
| 434 if (units) sprintf (buf, " %s", units); | |
| 435 } | |
| 436 | |
| 437 #ifdef OPAQUE_SPECIAL_TYPES | |
| 438 | |
| 439 static void | |
| 440 sprint_float(char *buf, | |
| 441 struct variable_list *var, | |
| 442 struct enum_list *enums, | |
| 443 const char *hint, | |
| 444 const char *units) | |
| 445 { | |
| 446 if (var->type != ASN_OPAQUE_FLOAT) { | |
| 447 sprintf(buf, "Wrong Type (should be Float): "); | |
| 448 buf += strlen(buf); | |
| 449 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 450 return; | |
| 451 } | |
| 452 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 453 sprintf(buf, "Opaque: Float:"); | |
| 454 buf += strlen(buf); | |
| 455 } | |
| 456 sprintf(buf, " %f", *var->val.floatVal); | |
| 457 buf += strlen (buf); | |
| 458 if (units) sprintf (buf, " %s", units); | |
| 459 } | |
| 460 | |
| 461 static void | |
| 462 sprint_double(char *buf, | |
| 463 struct variable_list *var, | |
| 464 struct enum_list *enums, | |
| 465 const char *hint, | |
| 466 const char *units) | |
| 467 { | |
| 468 if (var->type != ASN_OPAQUE_DOUBLE) { | |
| 469 sprintf(buf, "Wrong Type (should be Double): "); | |
| 470 buf += strlen(buf); | |
| 471 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 472 return; | |
| 473 } | |
| 474 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 475 sprintf(buf, "Opaque: Double:"); | |
| 476 buf += strlen(buf); | |
| 477 } | |
| 478 sprintf(buf, " %f", *var->val.doubleVal); | |
| 479 buf += strlen (buf); | |
| 480 if (units) sprintf (buf, " %s", units); | |
| 481 } | |
| 482 | |
| 483 #endif /* OPAQUE_SPECIAL_TYPES */ | |
| 484 | |
| 485 static void | |
| 486 sprint_opaque(char *buf, | |
| 487 struct variable_list *var, | |
| 488 struct enum_list *enums, | |
| 489 const char *hint, | |
| 490 const char *units) | |
| 491 { | |
| 492 | |
| 493 if (var->type != ASN_OPAQUE | |
| 494 #ifdef OPAQUE_SPECIAL_TYPES | |
| 495 && var->type != ASN_OPAQUE_COUNTER64 | |
| 496 && var->type != ASN_OPAQUE_U64 | |
| 497 && var->type != ASN_OPAQUE_I64 | |
| 498 && var->type != ASN_OPAQUE_FLOAT | |
| 499 && var->type != ASN_OPAQUE_DOUBLE | |
| 500 #endif /* OPAQUE_SPECIAL_TYPES */ | |
| 501 ){ | |
| 502 sprintf(buf, "Wrong Type (should be Opaque): "); | |
| 503 buf += strlen(buf); | |
| 504 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 505 return; | |
| 506 } | |
| 507 #ifdef OPAQUE_SPECIAL_TYPES | |
| 508 switch(var->type) { | |
| 509 case ASN_OPAQUE_COUNTER64: | |
| 510 case ASN_OPAQUE_U64: | |
| 511 case ASN_OPAQUE_I64: | |
| 512 sprint_counter64(buf, var, enums, hint, units); | |
| 513 break; | |
| 514 | |
| 515 case ASN_OPAQUE_FLOAT: | |
| 516 sprint_float(buf, var, enums, hint, units); | |
| 517 break; | |
| 518 | |
| 519 case ASN_OPAQUE_DOUBLE: | |
| 520 sprint_double(buf, var, enums, hint, units); | |
| 521 break; | |
| 522 | |
| 523 case ASN_OPAQUE: | |
| 524 #endif | |
| 525 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 526 sprintf(buf, "OPAQUE: "); | |
| 527 buf += strlen(buf); | |
| 528 } | |
| 529 sprint_hexstring(buf, var->val.string, var->val_len); | |
| 530 buf += strlen (buf); | |
| 531 #ifdef OPAQUE_SPECIAL_TYPES | |
| 532 } | |
| 533 #endif | |
| 534 if (units) sprintf (buf, " %s", units); | |
| 535 } | |
| 536 | |
| 537 static void | |
| 538 sprint_object_identifier(char *buf, | |
| 539 struct variable_list *var, | |
| 540 struct enum_list *enums, | |
| 541 const char *hint, | |
| 542 const char *units) | |
| 543 { | |
| 544 if (var->type != ASN_OBJECT_ID){ | |
| 545 sprintf(buf, "Wrong Type (should be OBJECT IDENTIFIER): "); | |
| 546 buf += strlen(buf); | |
| 547 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 548 return; | |
| 549 } | |
| 550 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 551 sprintf(buf, "OID: "); | |
| 552 buf += strlen(buf); | |
| 553 } | |
| 554 _sprint_objid(buf, (oid *)(var->val.objid), var->val_len / sizeof(oid)); | |
| 555 buf += strlen (buf); | |
| 556 if (units) sprintf (buf, " %s", units); | |
| 557 } | |
| 558 | |
| 559 static void | |
| 560 sprint_timeticks(char *buf, | |
| 561 struct variable_list *var, | |
| 562 struct enum_list *enums, | |
| 563 const char *hint, | |
| 564 const char *units) | |
| 565 { | |
| 566 char timebuf[32]; | |
| 567 | |
| 568 if (var->type != ASN_TIMETICKS){ | |
| 569 sprintf(buf, "Wrong Type (should be Timeticks): "); | |
| 570 buf += strlen(buf); | |
| 571 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 572 return; | |
| 573 } | |
| 574 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 575 sprintf(buf, "Timeticks: (%lu) ", *(u_long *)(var->val.integer)); | |
| 576 buf += strlen(buf); | |
| 577 } | |
| 578 sprintf(buf, "%s", uptimeString(*(u_long *)(var->val.integer), timebuf)); | |
| 579 buf += strlen (buf); | |
| 580 if (units) sprintf (buf, " %s", units); | |
| 581 } | |
| 582 | |
| 583 static void | |
| 584 sprint_hinted_integer (char *buf, | |
| 585 long val, | |
| 586 const char *hint, | |
| 587 const char *units) | |
| 588 { | |
| 589 char code; | |
| 590 int shift, len; | |
| 591 char tmp[256]; | |
| 592 char fmt[10]; | |
| 593 | |
| 594 code = hint[0]; | |
| 595 if (hint [1] == '-') { | |
| 596 shift = atoi (hint+2); | |
| 597 } | |
| 598 else shift = 0; | |
| 599 fmt[0] = '%'; | |
| 600 fmt[1] = 'l'; | |
| 601 fmt[2] = code; | |
| 602 fmt[3] = 0; | |
| 603 sprintf (tmp, fmt, val); | |
| 604 if (shift != 0) { | |
| 605 len = strlen (tmp); | |
| 606 if (shift <= len) { | |
| 607 tmp[len+1] = 0; | |
| 608 while (shift--) { | |
| 609 tmp[len] = tmp[len-1]; | |
| 610 len--; | |
| 611 } | |
| 612 tmp[len] = '.'; | |
| 613 } | |
| 614 else { | |
| 615 tmp[shift+1] = 0; | |
| 616 while (shift) { | |
| 617 if (len-- > 0) tmp [shift] = tmp [len]; | |
| 618 else tmp[shift] = '0'; | |
| 619 shift--; | |
| 620 } | |
| 621 tmp[0] = '.'; | |
| 622 } | |
| 623 } | |
| 624 strcpy (buf, tmp); | |
| 625 } | |
| 626 | |
| 627 static void | |
| 628 sprint_integer(char *buf, | |
| 629 struct variable_list *var, | |
| 630 struct enum_list *enums, | |
| 631 const char *hint, | |
| 632 const char *units) | |
| 633 { | |
| 634 char *enum_string = NULL; | |
| 635 | |
| 636 if (var->type != ASN_INTEGER){ | |
| 637 sprintf(buf, "Wrong Type (should be INTEGER): "); | |
| 638 buf += strlen(buf); | |
| 639 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 640 return; | |
| 641 } | |
| 642 for (; enums; enums = enums->next) | |
| 643 if (enums->value == *var->val.integer){ | |
| 644 enum_string = enums->label; | |
| 645 break; | |
| 646 } | |
| 647 if (enum_string == NULL || | |
| 648 ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_ENUM)) { | |
| 649 if (hint) sprint_hinted_integer(buf, *var->val.integer, hint, units); | |
| 650 else sprintf(buf, "%ld", *var->val.integer); | |
| 651 } | |
| 652 else if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) | |
| 653 sprintf(buf, "%s", enum_string); | |
| 654 else | |
| 655 sprintf(buf, "%s(%ld)", enum_string, *var->val.integer); | |
| 656 buf += strlen (buf); | |
| 657 if (units) sprintf (buf, " %s", units); | |
| 658 } | |
| 659 | |
| 660 static void | |
| 661 sprint_uinteger(char *buf, | |
| 662 struct variable_list *var, | |
| 663 struct enum_list *enums, | |
| 664 const char *hint, | |
| 665 const char *units) | |
| 666 { | |
| 667 char *enum_string = NULL; | |
| 668 | |
| 669 if (var->type != ASN_UINTEGER){ | |
| 670 sprintf(buf, "Wrong Type (should be UInteger32): "); | |
| 671 buf += strlen(buf); | |
| 672 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 673 return; | |
| 674 } | |
| 675 for (; enums; enums = enums->next) | |
| 676 if (enums->value == *var->val.integer){ | |
| 677 enum_string = enums->label; | |
| 678 break; | |
| 679 } | |
| 680 if (enum_string == NULL || | |
| 681 ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_ENUM)) | |
| 682 sprintf(buf, "%lu", *var->val.integer); | |
| 683 else if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) | |
| 684 sprintf(buf, "%s", enum_string); | |
| 685 else | |
| 686 sprintf(buf, "%s(%lu)", enum_string, *var->val.integer); | |
| 687 buf += strlen (buf); | |
| 688 if (units) sprintf (buf, " %s", units); | |
| 689 } | |
| 690 | |
| 691 static void | |
| 692 sprint_gauge(char *buf, | |
| 693 struct variable_list *var, | |
| 694 struct enum_list *enums, | |
| 695 const char *hint, | |
| 696 const char *units) | |
| 697 { | |
| 698 if (var->type != ASN_GAUGE){ | |
| 699 sprintf(buf, "Wrong Type (should be Gauge): "); | |
| 700 buf += strlen(buf); | |
| 701 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 702 return; | |
| 703 } | |
| 704 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) | |
| 705 sprintf(buf, "%lu", *var->val.integer); | |
| 706 else | |
| 707 sprintf(buf, "Gauge: %lu", *var->val.integer); | |
| 708 buf += strlen (buf); | |
| 709 if (units) sprintf (buf, " %s", units); | |
| 710 } | |
| 711 | |
| 712 static void | |
| 713 sprint_counter(char *buf, | |
| 714 struct variable_list *var, | |
| 715 struct enum_list *enums, | |
| 716 const char *hint, | |
| 717 const char *units) | |
| 718 { | |
| 719 if (var->type != ASN_COUNTER){ | |
| 720 sprintf(buf, "Wrong Type (should be Counter): "); | |
| 721 buf += strlen(buf); | |
| 722 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 723 return; | |
| 724 } | |
| 725 sprintf(buf, "%lu", *var->val.integer); | |
| 726 buf += strlen (buf); | |
| 727 if (units) sprintf (buf, " %s", units); | |
| 728 } | |
| 729 | |
| 730 static void | |
| 731 sprint_networkaddress(char *buf, | |
| 732 struct variable_list *var, | |
| 733 struct enum_list *enums, | |
| 734 const char *hint, | |
| 735 const char *units) | |
| 736 { | |
| 737 int x, len; | |
| 738 u_char *cp; | |
| 739 | |
| 740 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 741 sprintf(buf, "Network Address: "); | |
| 742 buf += strlen(buf); | |
| 743 } | |
| 744 cp = var->val.string; | |
| 745 len = var->val_len; | |
| 746 for(x = 0; x < len; x++){ | |
| 747 sprintf(buf, "%02X", *cp++); | |
| 748 buf += strlen(buf); | |
| 749 if (x < (len - 1)) | |
| 750 *buf++ = ':'; | |
| 751 } | |
| 752 } | |
| 753 | |
| 754 static void | |
| 755 sprint_ipaddress(char *buf, | |
| 756 struct variable_list *var, | |
| 757 struct enum_list *enums, | |
| 758 const char *hint, | |
| 759 const char *units) | |
| 760 { | |
| 761 u_char *ip; | |
| 762 | |
| 763 if (var->type != ASN_IPADDRESS){ | |
| 764 sprintf(buf, "Wrong Type (should be Ipaddress): "); | |
| 765 buf += strlen(buf); | |
| 766 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 767 return; | |
| 768 } | |
| 769 ip = var->val.string; | |
| 770 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) | |
| 771 sprintf(buf, "%d.%d.%d.%d",ip[0], ip[1], ip[2], ip[3]); | |
| 772 else | |
| 773 sprintf(buf, "IpAddress: %d.%d.%d.%d",ip[0], ip[1], ip[2], ip[3]); | |
| 774 } | |
| 775 | |
| 776 static void | |
| 777 sprint_null(char *buf, | |
| 778 struct variable_list *var, | |
| 779 struct enum_list *enums, | |
| 780 const char *hint, | |
| 781 const char *units) | |
| 782 { | |
| 783 if (var->type != ASN_NULL){ | |
| 784 sprintf(buf, "Wrong Type (should be NULL): "); | |
| 785 buf += strlen(buf); | |
| 786 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 787 return; | |
| 788 } | |
| 789 sprintf(buf, "NULL"); | |
| 790 } | |
| 791 | |
| 792 static void | |
| 793 sprint_bitstring(char *buf, | |
| 794 struct variable_list *var, | |
| 795 struct enum_list *enums, | |
| 796 const char *hint, | |
| 797 const char *units) | |
| 798 { | |
| 799 int len, bit; | |
| 800 u_char *cp; | |
| 801 char *enum_string; | |
| 802 | |
| 803 if (var->type != ASN_BIT_STR && var->type != ASN_OCTET_STR){ | |
| 804 sprintf(buf, "Wrong Type (should be BIT STRING): "); | |
| 805 buf += strlen(buf); | |
| 806 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 807 return; | |
| 808 } | |
| 809 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 810 *buf++ = '"'; | |
| 811 *buf = '\0'; | |
| 812 } else { | |
| 813 sprintf(buf, "BITS: "); | |
| 814 buf += strlen(buf); | |
| 815 } | |
| 816 sprint_hexstring(buf, var->val.bitstring, var->val_len); | |
| 817 buf += strlen(buf); | |
| 818 | |
| 819 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 820 buf += strlen(buf); | |
| 821 *buf++ = '"'; | |
| 822 *buf = '\0'; | |
| 823 } else { | |
| 824 cp = var->val.bitstring; | |
| 825 for(len = 0; len < (int)var->val_len; len++){ | |
| 826 for(bit = 0; bit < 8; bit++){ | |
| 827 if (*cp & (0x80 >> bit)){ | |
| 828 enum_string = NULL; | |
| 829 for (; enums; enums = enums->next) | |
| 830 if (enums->value == (len * 8) + bit){ | |
| 831 enum_string = enums->label; | |
| 832 break; | |
| 833 } | |
| 834 if (enum_string == NULL || | |
| 835 ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_ENUM)) | |
| 836 sprintf(buf, "%d ", (len * 8) + bit); | |
| 837 else | |
| 838 sprintf(buf, "%s(%d) ", enum_string, (len * 8) + bit); | |
| 839 buf += strlen(buf); | |
| 840 } | |
| 841 } | |
| 842 cp ++; | |
| 843 } | |
| 844 } | |
| 845 } | |
| 846 | |
| 847 static void | |
| 848 sprint_nsapaddress(char *buf, | |
| 849 struct variable_list *var, | |
| 850 struct enum_list *enums, | |
| 851 const char *hint, | |
| 852 const char *units) | |
| 853 { | |
| 854 if (var->type != ASN_NSAP){ | |
| 855 sprintf(buf, "Wrong Type (should be NsapAddress): "); | |
| 856 buf += strlen(buf); | |
| 857 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 858 return; | |
| 859 } | |
| 860 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 861 sprintf(buf, "NsapAddress: "); | |
| 862 buf += strlen(buf); | |
| 863 } | |
| 864 sprint_hexstring(buf, var->val.string, var->val_len); | |
| 865 } | |
| 866 | |
| 867 static void | |
| 868 sprint_counter64(char *buf, | |
| 869 struct variable_list *var, | |
| 870 struct enum_list *enums, | |
| 871 const char *hint, | |
| 872 const char *units) | |
| 873 { | |
| 874 char a64buf[I64CHARSZ+1]; | |
| 875 | |
| 876 if (var->type != ASN_COUNTER64 | |
| 877 #ifdef OPAQUE_SPECIAL_TYPES | |
| 878 && var->type != ASN_OPAQUE_COUNTER64 | |
| 879 && var->type != ASN_OPAQUE_I64 | |
| 880 && var->type != ASN_OPAQUE_U64 | |
| 881 #endif | |
| 882 ){ | |
| 883 sprintf(buf, "Wrong Type (should be Counter64): "); | |
| 884 buf += strlen(buf); | |
| 885 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 886 return; | |
| 887 } | |
| 888 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)){ | |
| 889 #ifdef OPAQUE_SPECIAL_TYPES | |
| 890 if (var->type != ASN_COUNTER64) { | |
| 891 sprintf(buf, "Opaque: "); | |
| 892 buf += strlen(buf); | |
| 893 } | |
| 894 #endif | |
| 895 #ifdef OPAQUE_SPECIAL_TYPES | |
| 896 switch(var->type) { | |
| 897 case ASN_OPAQUE_U64: | |
| 898 sprintf(buf, "UInt64: "); | |
| 899 break; | |
| 900 case ASN_OPAQUE_I64: | |
| 901 sprintf(buf, "Int64: "); | |
| 902 break; | |
| 903 case ASN_COUNTER64: | |
| 904 case ASN_OPAQUE_COUNTER64: | |
| 905 #endif | |
| 906 sprintf(buf, "Counter64: "); | |
| 907 #ifdef OPAQUE_SPECIAL_TYPES | |
| 908 } | |
| 909 #endif | |
| 910 buf += strlen(buf); | |
| 911 } | |
| 912 #ifdef OPAQUE_SPECIAL_TYPES | |
| 913 if (var->type == ASN_OPAQUE_I64) | |
| 914 { | |
| 915 printI64(a64buf, var->val.counter64); | |
| 916 sprintf(buf, a64buf); | |
| 917 } | |
| 918 else | |
| 919 #endif | |
| 920 { | |
| 921 printU64(a64buf, var->val.counter64); | |
| 922 sprintf(buf, a64buf); | |
| 923 } | |
| 924 buf += strlen (buf); | |
| 925 if (units) sprintf (buf, " %s", units); | |
| 926 } | |
| 927 | |
| 928 static void | |
| 929 sprint_unknowntype(char *buf, | |
| 930 struct variable_list *var, | |
| 931 struct enum_list *enums, | |
| 932 const char *hint, | |
| 933 const char *units) | |
| 934 { | |
| 935 /* sprintf(buf, "Variable has bad type"); */ | |
| 936 sprint_by_type(buf, var, NULL, NULL, NULL); | |
| 937 } | |
| 938 | |
| 939 static void | |
| 940 sprint_badtype(char *buf, | |
| 941 struct variable_list *var, | |
| 942 struct enum_list *enums, | |
| 943 const char *hint, | |
| 944 const char *units) | |
| 945 { | |
| 946 sprintf(buf, "Variable has bad type"); | |
| 947 } | |
| 948 | |
| 949 static void | |
| 950 sprint_by_type(char *buf, | |
| 951 struct variable_list *var, | |
| 952 struct enum_list *enums, | |
| 953 const char *hint, | |
| 954 const char *units) | |
| 955 { | |
| 956 switch (var->type){ | |
| 957 case ASN_INTEGER: | |
| 958 sprint_integer(buf, var, enums, hint, units); | |
| 959 break; | |
| 960 case ASN_OCTET_STR: | |
| 961 sprint_octet_string(buf, var, enums, hint, units); | |
| 962 break; | |
| 963 case ASN_BIT_STR: | |
| 964 sprint_bitstring(buf, var, enums, hint, units); | |
| 965 break; | |
| 966 case ASN_OPAQUE: | |
| 967 sprint_opaque(buf, var, enums, hint, units); | |
| 968 break; | |
| 969 case ASN_OBJECT_ID: | |
| 970 sprint_object_identifier(buf, var, enums, hint, units); | |
| 971 break; | |
| 972 case ASN_TIMETICKS: | |
| 973 sprint_timeticks(buf, var, enums, hint, units); | |
| 974 break; | |
| 975 case ASN_GAUGE: | |
| 976 sprint_gauge(buf, var, enums, hint, units); | |
| 977 break; | |
| 978 case ASN_COUNTER: | |
| 979 sprint_counter(buf, var, enums, hint, units); | |
| 980 break; | |
| 981 case ASN_IPADDRESS: | |
| 982 sprint_ipaddress(buf, var, enums, hint, units); | |
| 983 break; | |
| 984 case ASN_NULL: | |
| 985 sprint_null(buf, var, enums, hint, units); | |
| 986 break; | |
| 987 case ASN_UINTEGER: | |
| 988 sprint_uinteger(buf, var, enums, hint, units); | |
| 989 break; | |
| 990 case ASN_COUNTER64: | |
| 991 #ifdef OPAQUE_SPECIAL_TYPES | |
| 992 case ASN_OPAQUE_U64: | |
| 993 case ASN_OPAQUE_I64: | |
| 994 case ASN_OPAQUE_COUNTER64: | |
| 995 #endif /* OPAQUE_SPECIAL_TYPES */ | |
| 996 sprint_counter64(buf, var, enums, hint, units); | |
| 997 break; | |
| 998 #ifdef OPAQUE_SPECIAL_TYPES | |
| 999 case ASN_OPAQUE_FLOAT: | |
| 1000 sprint_float(buf, var, enums, hint, units); | |
| 1001 break; | |
| 1002 case ASN_OPAQUE_DOUBLE: | |
| 1003 sprint_double(buf, var, enums, hint, units); | |
| 1004 break; | |
| 1005 #endif /* OPAQUE_SPECIAL_TYPES */ | |
| 1006 default: | |
| 1007 DEBUGMSGTL(("sprint_by_type", "bad type: %d\n", var->type)); | |
| 1008 sprint_badtype(buf, var, enums, hint, units); | |
| 1009 break; | |
| 1010 } | |
| 1011 } | |
| 1012 | |
| 1013 | |
| 1014 struct tree *get_tree_head(void) | |
| 1015 { | |
| 1016 return(tree_head); | |
| 1017 } | |
| 1018 | |
| 1019 static char *confmibdir=NULL; | |
| 1020 static char *confmibs=NULL; | |
| 1021 | |
| 1022 void | |
| 1023 handle_mibdirs_conf(const char *token, | |
| 1024 char *line) | |
| 1025 { | |
| 1026 char *ctmp; | |
| 1027 | |
| 1028 if (confmibdir) { | |
| 1029 ctmp = (char *)malloc(strlen(confmibdir) + strlen(line) + 1); | |
| 1030 if (*line == '+') | |
| 1031 line++; | |
| 1032 sprintf(ctmp,"%s%c%s",confmibdir, ENV_SEPARATOR_CHAR, line); | |
| 1033 free(confmibdir); | |
| 1034 confmibdir = ctmp; | |
| 1035 } else { | |
| 1036 confmibdir=strdup(line); | |
| 1037 } | |
| 1038 DEBUGMSGTL(("read_config:initmib", "using mibdirs: %s\n", confmibdir)); | |
| 1039 } | |
| 1040 | |
| 1041 void | |
| 1042 handle_mibs_conf(const char *token, | |
| 1043 char *line) | |
| 1044 { | |
| 1045 char *ctmp; | |
| 1046 | |
| 1047 if (confmibs) { | |
| 1048 ctmp = (char *)malloc(strlen(confmibs) + strlen(line) + 1); | |
| 1049 if (*line == '+') | |
| 1050 line++; | |
| 1051 sprintf(ctmp,"%s%c%s",confmibs, ENV_SEPARATOR_CHAR, line); | |
| 1052 free(confmibs); | |
| 1053 confmibs = ctmp; | |
| 1054 } else { | |
| 1055 confmibs=strdup(line); | |
| 1056 } | |
| 1057 DEBUGMSGTL(("read_config:initmib", "using mibs: %s\n", confmibs)); | |
| 1058 } | |
| 1059 | |
| 1060 void | |
| 1061 handle_mibfile_conf(const char *token, | |
| 1062 char *line) | |
| 1063 { | |
| 1064 DEBUGMSGTL(("read_config:initmib", "reading mibfile: %s\n", line)); | |
| 1065 read_mib(line); | |
| 1066 } | |
| 1067 | |
| 1068 char * | |
| 1069 snmp_out_toggle_options(char *options) | |
| 1070 { | |
| 1071 while(*options) { | |
| 1072 switch(*options++) { | |
| 1073 case 'n': | |
| 1074 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_OIDS); | |
| 1075 break; | |
| 1076 case 'e': | |
| 1077 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_ENUM); | |
| 1078 break; | |
| 1079 case 'b': | |
| 1080 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_DONT_BREAKDOWN_OIDS); | |
| 1081 break; | |
| 1082 case 'q': | |
| 1083 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT); | |
| 1084 break; | |
| 1085 case 'f': | |
| 1086 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_FULL_OID); | |
| 1087 break; | |
| 1088 case 's': | |
| 1089 snmp_set_suffix_only(1); | |
| 1090 break; | |
| 1091 case 'S': | |
| 1092 snmp_set_suffix_only(2); | |
| 1093 break; | |
| 1094 default: | |
| 1095 return options-1; | |
| 1096 } | |
| 1097 } | |
| 1098 return NULL; | |
| 1099 } | |
| 1100 | |
| 1101 void snmp_out_toggle_options_usage(const char *lead, FILE *outf) | |
| 1102 { | |
| 1103 fprintf(outf, "%sOUTOPTS values:\n", lead); | |
| 1104 fprintf(outf, "%s n: Print oids numerically.\n", lead); | |
| 1105 fprintf(outf, "%s e: Print enums numerically.\n", lead); | |
| 1106 fprintf(outf, "%s b: Dont break oid indexes down.\n", lead); | |
| 1107 fprintf(outf, "%s q: Quick print for easier parsing.\n", lead); | |
| 1108 fprintf(outf, "%s f: Print full oids on output.\n", lead); | |
| 1109 fprintf(outf, "%s s: Print only last symbolic element of oid.\n", lead); | |
| 1110 fprintf(outf, "%s S: Print MIB module-id plus last element.\n", lead); | |
| 1111 } | |
| 1112 | |
| 1113 char * | |
| 1114 snmp_in_toggle_options(char *options) | |
| 1115 { | |
| 1116 while(*options) { | |
| 1117 switch(*options++) { | |
| 1118 case 'R': | |
| 1119 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_RANDOM_ACCESS); | |
| 1120 break; | |
| 1121 case 'b': | |
| 1122 ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_REGEX_ACCESS); | |
| 1123 break; | |
| 1124 default: | |
| 1125 return options-1; | |
| 1126 } | |
| 1127 } | |
| 1128 return NULL; | |
| 1129 } | |
| 1130 | |
| 1131 void snmp_in_toggle_options_usage(const char *lead, FILE *outf) | |
| 1132 { | |
| 1133 fprintf(outf, "%sINOPTS values:\n", lead); | |
| 1134 fprintf(outf, "%s R: Do random access to oid labels.\n", lead); | |
| 1135 fprintf(outf, "%s b: Do best/regex matching to find a MIB node.\n", lead); | |
| 1136 } | |
| 1137 | |
| 1138 void | |
| 1139 register_mib_handlers (void) | |
| 1140 { | |
| 1141 register_premib_handler("snmp","mibdirs", | |
| 1142 handle_mibdirs_conf, NULL, | |
| 1143 "[mib-dirs|+mib-dirs]"); | |
| 1144 register_premib_handler("snmp","mibs", | |
| 1145 handle_mibs_conf,NULL, | |
| 1146 "[mib-tokens|+mib-tokens]"); | |
| 1147 register_config_handler("snmp","mibfile", | |
| 1148 handle_mibfile_conf, NULL, | |
| 1149 "mibfile-to-read"); | |
| 1150 | |
| 1151 /* register the snmp.conf configuration handlers for default | |
| 1152 parsing behaviour */ | |
| 1153 | |
| 1154 ds_register_premib(ASN_BOOLEAN, "snmp","showMibErrors", | |
| 1155 DS_LIBRARY_ID, DS_LIB_MIB_ERRORS); | |
| 1156 ds_register_premib(ASN_BOOLEAN, "snmp","strictCommentTerm", | |
| 1157 DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM); | |
| 1158 ds_register_premib(ASN_BOOLEAN, "snmp","mibAllowUnderline", | |
| 1159 DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL); | |
| 1160 ds_register_premib(ASN_INTEGER, "snmp","mibWarningLevel", | |
| 1161 DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS); | |
| 1162 ds_register_premib(ASN_BOOLEAN, "snmp","mibReplaceWithLatest", | |
| 1163 DS_LIBRARY_ID, DS_LIB_MIB_REPLACE); | |
| 1164 | |
| 1165 ds_register_config(ASN_BOOLEAN, "snmp","printNumericEnums", | |
| 1166 DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_ENUM); | |
| 1167 ds_register_config(ASN_BOOLEAN, "snmp","printNumericOids", | |
| 1168 DS_LIBRARY_ID, DS_LIB_PRINT_NUMERIC_OIDS); | |
| 1169 ds_register_config(ASN_BOOLEAN, "snmp","dontBreakdownOids", | |
| 1170 DS_LIBRARY_ID, DS_LIB_DONT_BREAKDOWN_OIDS); | |
| 1171 ds_register_config(ASN_BOOLEAN, "snmp","quickPrinting", | |
| 1172 DS_LIBRARY_ID, DS_LIB_QUICK_PRINT); | |
| 1173 ds_register_config(ASN_INTEGER, "snmp","suffixPrinting", | |
| 1174 DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY); | |
| 1175 | |
| 1176 /* setup the default parser configurations, as specified by configure */ | |
| 1177 #ifdef MIB_COMMENT_IS_EOL_TERMINATED | |
| 1178 ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM, 1); | |
| 1179 #else /* !MIB_COMMENT_IS_EOL_TERMINATED */ | |
| 1180 ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM, 0); | |
| 1181 #endif /* !MIB_COMMENT_IS_EOL_TERMINATED */ | |
| 1182 } | |
| 1183 | |
| 1184 void | |
| 1185 init_mib (void) | |
| 1186 { | |
| 1187 const char *prefix; | |
| 1188 char *env_var, *entry; | |
| 1189 PrefixListPtr pp = &mib_prefixes[0]; | |
| 1190 char *new_mibdirs, *homepath, *cp_home; | |
| 1191 | |
| 1192 if (Mib) return; | |
| 1193 | |
| 1194 /* Initialise the MIB directory/ies */ | |
| 1195 | |
| 1196 /* we can't use the environment variable directly, because strtok | |
| 1197 will modify it. */ | |
| 1198 | |
| 1199 env_var = getenv("MIBDIRS"); | |
| 1200 if ( env_var == NULL ) { | |
| 1201 if (confmibdir != NULL) | |
| 1202 env_var = strdup(confmibdir); | |
| 1203 else | |
| 1204 env_var = strdup(DEFAULT_MIBDIRS); | |
| 1205 } else { | |
| 1206 env_var = strdup(env_var); | |
| 1207 } | |
| 1208 if (*env_var == '+') { | |
| 1209 entry = (char *)malloc(strlen(DEFAULT_MIBDIRS)+strlen(env_var)+2); | |
| 1210 sprintf(entry, "%s%c%s", DEFAULT_MIBDIRS, ENV_SEPARATOR_CHAR, env_var+1); | |
| 1211 free(env_var); | |
| 1212 env_var = entry; | |
| 1213 } | |
| 1214 | |
| 1215 /* replace $HOME in the path with the users home directory */ | |
| 1216 homepath=getenv("HOME"); | |
| 1217 | |
| 1218 if (homepath) { | |
| 1219 while((cp_home = strstr(env_var, "$HOME"))) { | |
| 1220 new_mibdirs = (char *) malloc(strlen(env_var) - strlen("$HOME") + | |
| 1221 strlen(homepath)+1); | |
| 1222 *cp_home = 0; /* null out the spot where we stop copying */ | |
| 1223 sprintf(new_mibdirs, "%s%s%s", env_var, homepath, | |
| 1224 cp_home + strlen("$HOME")); | |
| 1225 /* swap in the new value and repeat */ | |
| 1226 free(env_var); | |
| 1227 env_var = new_mibdirs; | |
| 1228 } | |
| 1229 } | |
| 1230 | |
| 1231 DEBUGMSGTL(("init_mib","Seen MIBDIRS: Looking in '%s' for mib dirs ...\n",env_var)); | |
| 1232 | |
| 1233 entry = strtok( env_var, ENV_SEPARATOR ); | |
| 1234 while ( entry ) { | |
| 1235 add_mibdir(entry); | |
| 1236 entry = strtok( NULL, ENV_SEPARATOR); | |
| 1237 } | |
| 1238 free(env_var); | |
| 1239 | |
| 1240 init_mib_internals(); | |
| 1241 | |
| 1242 /* Read in any modules or mibs requested */ | |
| 1243 | |
| 1244 env_var = getenv("MIBS"); | |
| 1245 if ( env_var == NULL ) { | |
| 1246 if (confmibs != NULL) | |
| 1247 env_var = strdup(confmibs); | |
| 1248 else | |
| 1249 env_var = strdup(DEFAULT_MIBS); | |
| 1250 } else { | |
| 1251 env_var = strdup(env_var); | |
| 1252 } | |
| 1253 if (*env_var == '+') { | |
| 1254 entry = (char *)malloc(strlen(DEFAULT_MIBS)+strlen(env_var)+2); | |
| 1255 sprintf(entry, "%s%c%s", DEFAULT_MIBS, ENV_SEPARATOR_CHAR, env_var+1); | |
| 1256 free(env_var); | |
| 1257 env_var = entry; | |
| 1258 } | |
| 1259 | |
| 1260 DEBUGMSGTL(("init_mib","Seen MIBS: Looking in '%s' for mib files ...\n",env_var)); | |
| 1261 entry = strtok( env_var, ENV_SEPARATOR ); | |
| 1262 while ( entry ) { | |
| 1263 if (strcasecmp(entry, DEBUG_ALWAYS_TOKEN) == 0) { | |
| 1264 read_all_mibs(); | |
| 1265 } | |
| 1266 else if (strstr (entry, "/") != 0) { | |
| 1267 read_mib(entry); | |
| 1268 } | |
| 1269 else { | |
| 1270 read_module(entry); | |
| 1271 } | |
| 1272 entry = strtok( NULL, ENV_SEPARATOR); | |
| 1273 } | |
| 1274 adopt_orphans(); | |
| 1275 free(env_var); | |
| 1276 | |
| 1277 env_var = getenv("MIBFILES"); | |
| 1278 if ( env_var != NULL ) { | |
| 1279 if (*env_var == '+') { | |
| 1280 #ifdef DEFAULT_MIBFILES | |
| 1281 entry = (char *)malloc(strlen(DEFAULT_MIBFILES)+strlen(env_var)+2); | |
| 1282 sprintf(entry, "%s%c%s", DEFAULT_MIBFILES, ENV_SEPARATOR_CHAR, | |
| 1283 env_var+1); | |
| 1284 free(env_var); | |
| 1285 env_var = entry; | |
| 1286 #else | |
| 1287 env_var = strdup(env_var+1); | |
| 1288 #endif | |
| 1289 } else { | |
| 1290 env_var = strdup(env_var); | |
| 1291 } | |
| 1292 } else { | |
| 1293 #ifdef DEFAULT_MIBFILES | |
| 1294 env_var = strdup(DEFAULT_MIBFILES); | |
| 1295 #endif | |
| 1296 } | |
| 1297 | |
| 1298 if ( env_var != 0 ) { | |
| 1299 DEBUGMSGTL(("init_mib","Seen MIBFILES: Looking in '%s' for mib files ...\n",env_var)); | |
| 1300 entry = strtok( env_var, ENV_SEPARATOR ); | |
| 1301 while ( entry ) { | |
| 1302 read_mib(entry); | |
| 1303 entry = strtok( NULL, ENV_SEPARATOR); | |
| 1304 } | |
| 1305 free(env_var); | |
| 1306 } | |
| 1307 | |
| 1308 prefix = getenv("PREFIX"); | |
| 1309 | |
| 1310 if (!prefix) | |
| 1311 prefix = Standard_Prefix; | |
| 1312 | |
| 1313 Prefix = (char*)malloc(strlen(prefix)+2); | |
| 1314 strcpy(Prefix, prefix); | |
| 1315 | |
| 1316 DEBUGMSGTL(("init_mib","Seen PREFIX: Looking in '%s' for prefix ...\n", Prefix)); | |
| 1317 | |
| 1318 /* remove trailing dot */ | |
| 1319 env_var = &Prefix[strlen(Prefix) - 1]; | |
| 1320 if (*env_var == '.') *env_var = '\0'; | |
| 1321 | |
| 1322 pp->str = Prefix; /* fixup first mib_prefix entry */ | |
| 1323 /* now that the list of prefixes is built, save each string length. */ | |
| 1324 while (pp->str) { | |
| 1325 pp->len = strlen(pp->str); | |
| 1326 pp++; | |
| 1327 } | |
| 1328 | |
| 1329 if (getenv("SUFFIX")) | |
| 1330 ds_set_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY, 1); | |
| 1331 | |
| 1332 Mib = tree_head; /* Backwards compatibility */ | |
| 1333 } | |
| 1334 | |
| 1335 void | |
| 1336 print_mib (FILE *fp) | |
| 1337 { | |
| 1338 print_subtree (fp, tree_head, 0); | |
| 1339 } | |
| 1340 | |
| 1341 void | |
| 1342 print_ascii_dump (FILE *fp) | |
| 1343 { | |
| 1344 fprintf(fp, "dump DEFINITIONS ::= BEGIN\n"); | |
| 1345 print_ascii_dump_tree (fp, tree_head, 0); | |
| 1346 fprintf(fp, "END\n"); | |
| 1347 } | |
| 1348 | |
| 1349 void | |
| 1350 set_function(struct tree *subtree) | |
| 1351 { | |
| 1352 switch(subtree->type){ | |
| 1353 case TYPE_OBJID: | |
| 1354 subtree->printer = sprint_object_identifier; | |
| 1355 break; | |
| 1356 case TYPE_OCTETSTR: | |
| 1357 subtree->printer = sprint_octet_string; | |
| 1358 break; | |
| 1359 case TYPE_INTEGER: | |
| 1360 subtree->printer = sprint_integer; | |
| 1361 break; | |
| 1362 case TYPE_NETADDR: | |
| 1363 subtree->printer = sprint_networkaddress; | |
| 1364 break; | |
| 1365 case TYPE_IPADDR: | |
| 1366 subtree->printer = sprint_ipaddress; | |
| 1367 break; | |
| 1368 case TYPE_COUNTER: | |
| 1369 subtree->printer = sprint_counter; | |
| 1370 break; | |
| 1371 case TYPE_GAUGE: | |
| 1372 subtree->printer = sprint_gauge; | |
| 1373 break; | |
| 1374 case TYPE_TIMETICKS: | |
| 1375 subtree->printer = sprint_timeticks; | |
| 1376 break; | |
| 1377 case TYPE_OPAQUE: | |
| 1378 subtree->printer = sprint_opaque; | |
| 1379 break; | |
| 1380 case TYPE_NULL: | |
| 1381 subtree->printer = sprint_null; | |
| 1382 break; | |
| 1383 case TYPE_BITSTRING: | |
| 1384 subtree->printer = sprint_bitstring; | |
| 1385 break; | |
| 1386 case TYPE_NSAPADDRESS: | |
| 1387 subtree->printer = sprint_nsapaddress; | |
| 1388 break; | |
| 1389 case TYPE_COUNTER64: | |
| 1390 subtree->printer = sprint_counter64; | |
| 1391 break; | |
| 1392 case TYPE_UINTEGER: | |
| 1393 subtree->printer = sprint_uinteger; | |
| 1394 break; | |
| 1395 case TYPE_OTHER: | |
| 1396 default: | |
| 1397 subtree->printer = sprint_unknowntype; | |
| 1398 break; | |
| 1399 } | |
| 1400 } | |
| 1401 | |
| 1402 /* | |
| 1403 * Read an object identifier from input string into internal OID form. | |
| 1404 * Returns 1 if successful. | |
| 1405 * If an error occurs, this function returns 0 and MAY set snmp_errno. | |
| 1406 * snmp_errno is NOT set if SET_SNMP_ERROR evaluates to nothing. | |
| 1407 * This can make multi-threaded use a tiny bit more robust. | |
| 1408 */ | |
| 1409 int read_objid(const char *input, | |
| 1410 oid *output, | |
| 1411 size_t *out_len) /* number of subid's in "output" */ | |
| 1412 { | |
| 1413 struct tree *root = tree_head; | |
| 1414 char buf[SPRINT_MAX_LEN]; | |
| 1415 int ret; | |
| 1416 | |
| 1417 if (strchr(input, ':')) { | |
| 1418 return get_node(input, output, out_len); | |
| 1419 } | |
| 1420 | |
| 1421 if (*input == '.') | |
| 1422 input++; | |
| 1423 else { | |
| 1424 /* get past leading '.', append '.' to Prefix. */ | |
| 1425 if (*Prefix == '.') | |
| 1426 strcpy(buf, Prefix+1); | |
| 1427 else | |
| 1428 strcpy(buf, Prefix); | |
| 1429 strcat(buf, "."); | |
| 1430 strcat(buf, input); | |
| 1431 input = buf; | |
| 1432 } | |
| 1433 | |
| 1434 if (root == NULL){ | |
| 1435 SET_SNMP_ERROR(SNMPERR_NOMIB); | |
| 1436 *out_len = 0; | |
| 1437 return(0); | |
| 1438 } | |
| 1439 if ((ret = parse_subtree(root, input, output, out_len)) <= 0) | |
| 1440 { | |
| 1441 int errc = (ret ? ret : SNMPERR_UNKNOWN_OBJID); | |
| 1442 SET_SNMP_ERROR(errc); | |
| 1443 return (0); | |
| 1444 } | |
| 1445 *out_len = ret; | |
| 1446 | |
| 1447 return (1); | |
| 1448 } | |
| 1449 | |
| 1450 | |
| 1451 /* | |
| 1452 * RECURSIVE helper methods for read_objid | |
| 1453 * Returns: | |
| 1454 * < 0 the SNMPERR_ errorcode | |
| 1455 * = 0 input string is empty. | |
| 1456 * > 0 the number of sub-identifiers found in the input string. | |
| 1457 */ | |
| 1458 static int | |
| 1459 parse_subtree(struct tree *subtree, | |
| 1460 const char *input, | |
| 1461 oid *output, | |
| 1462 size_t *out_len) /* number of subid's */ | |
| 1463 { | |
| 1464 char buf[SPRINT_MAX_LEN], *to = buf, *cp; | |
| 1465 u_long subid = 0; | |
| 1466 struct tree *tp; | |
| 1467 int ret, len; | |
| 1468 | |
| 1469 /* | |
| 1470 * No empty strings. Can happen if there is a trailing '.' or two '.'s | |
| 1471 * in a row, i.e. "..". | |
| 1472 */ | |
| 1473 if ((*input == '\0') || | |
| 1474 (*input == '.')) | |
| 1475 return (0); | |
| 1476 | |
| 1477 if (*input == '"' || *input == '\'') { | |
| 1478 /* | |
| 1479 * This is a string that should be converted into an OID | |
| 1480 * Note: assumes variable length index is required, and prepends | |
| 1481 * the string length. | |
| 1482 */ | |
| 1483 if ((cp = strchr(input+1, *input)) == NULL) { | |
| 1484 /* error. Should be a matching quote somewhere. */ | |
| 1485 return (0); | |
| 1486 } | |
| 1487 | |
| 1488 /* is there room enough for the string in question plus its length */ | |
| 1489 len = cp-input-1; | |
| 1490 if ((int)*out_len <= len){ | |
| 1491 return (SNMPERR_LONG_OID); | |
| 1492 } | |
| 1493 | |
| 1494 /* copy everything in */ | |
| 1495 if (*input++ == '"') { | |
| 1496 /* add the length for " quoted objects */ | |
| 1497 *output++ = len++; | |
| 1498 } | |
| 1499 | |
| 1500 *out_len -= len; | |
| 1501 while (input < cp) { | |
| 1502 *output++ = *input++; | |
| 1503 } | |
| 1504 | |
| 1505 /* Now, we assume that nothing beyond this exists in the parse | |
| 1506 tree, which should always be true (or else we have a really wacked | |
| 1507 mib designer somewhere. */ | |
| 1508 input = cp + 1; /* past the quote */ | |
| 1509 | |
| 1510 if (*input != '.') | |
| 1511 return (len); | |
| 1512 | |
| 1513 ret = parse_subtree(NULL, ++input, output, out_len); | |
| 1514 if (ret <= 0) | |
| 1515 return (ret); | |
| 1516 return ret+len; | |
| 1517 | |
| 1518 } else if (isdigit(*input)) { | |
| 1519 /* | |
| 1520 * Read the number, then try to find it in the subtree. | |
| 1521 */ | |
| 1522 while (isdigit(*input)) { | |
| 1523 *to++ = *input; | |
| 1524 subid *= 10; | |
| 1525 subid += *input++ - '0'; | |
| 1526 } | |
| 1527 if (*input != '.' && *input != 0) { | |
| 1528 while (*input != 0 && *input != '.') *to++ = *input++; | |
| 1529 *to = 0; | |
| 1530 snmp_set_detail(buf); | |
| 1531 return SNMPERR_BAD_SUBID; | |
| 1532 } | |
| 1533 *to = '\0'; | |
| 1534 | |
| 1535 for (tp = subtree; tp; tp = tp->next_peer) { | |
| 1536 if (tp->subid == subid) | |
| 1537 goto found; | |
| 1538 } | |
| 1539 } | |
| 1540 else { | |
| 1541 /* | |
| 1542 * Read the name into a buffer. | |
| 1543 */ | |
| 1544 while ((*input != '\0') && | |
| 1545 (*input != '.')) { | |
| 1546 *to++ = *input++; | |
| 1547 } | |
| 1548 *to = '\0'; | |
| 1549 | |
| 1550 /* | |
| 1551 * Find the name in the subtree; | |
| 1552 */ | |
| 1553 for (tp = subtree; tp; tp = tp->next_peer) { | |
| 1554 if (strcasecmp(tp->label, buf) == 0) { | |
| 1555 subid = tp->subid; | |
| 1556 goto found; | |
| 1557 } | |
| 1558 } | |
| 1559 | |
| 1560 /* | |
| 1561 * If we didn't find the entry, punt... | |
| 1562 */ | |
| 1563 if (tp == NULL) { | |
| 1564 snmp_set_detail(buf); | |
| 1565 return (SNMPERR_BAD_SUBID); | |
| 1566 } | |
| 1567 } | |
| 1568 | |
| 1569 found: | |
| 1570 if(subid > (u_long)MAX_SUBID){ | |
| 1571 snmp_set_detail(buf); | |
| 1572 return (SNMPERR_MAX_SUBID); | |
| 1573 } | |
| 1574 | |
| 1575 if ((int)*out_len <= 0){ | |
| 1576 return (SNMPERR_LONG_OID); | |
| 1577 } | |
| 1578 | |
| 1579 (*out_len)--; | |
| 1580 *output++ = subid; | |
| 1581 | |
| 1582 if (*input != '.') | |
| 1583 return (1); | |
| 1584 | |
| 1585 ret = parse_subtree(tp ? tp->child_list : NULL, | |
| 1586 ++input, output, out_len); | |
| 1587 if (ret <= 0) | |
| 1588 return (ret); | |
| 1589 return ret+1; | |
| 1590 } | |
| 1591 | |
| 1592 static struct tree * | |
| 1593 _sprint_objid(char *buf, | |
| 1594 oid *objid, | |
| 1595 size_t objidlen) /* number of subidentifiers */ | |
| 1596 { | |
| 1597 char tempbuf[SPRINT_MAX_LEN], *cp; | |
| 1598 struct tree *subtree = tree_head; | |
| 1599 char *midpoint = 0; | |
| 1600 | |
| 1601 *tempbuf = '.'; /* this is a fully qualified name */ | |
| 1602 subtree = _get_symbol(objid, objidlen, subtree, tempbuf + 1, 0, &midpoint); | |
| 1603 if (ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_OIDS)) { | |
| 1604 cp = tempbuf; | |
| 1605 } else if (ds_get_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY)){ | |
| 1606 for(cp = tempbuf; *cp; cp++) | |
| 1607 ; | |
| 1608 if (midpoint) | |
| 1609 cp = midpoint-2; /* beyond the '.' */ | |
| 1610 else { | |
| 1611 while(cp >= tempbuf){ | |
| 1612 if (isalpha(*cp)) | |
| 1613 break; | |
| 1614 cp--; | |
| 1615 } | |
| 1616 } | |
| 1617 while(cp >= tempbuf){ | |
| 1618 if (*cp == '.') | |
| 1619 break; | |
| 1620 cp--; | |
| 1621 } | |
| 1622 cp++; | |
| 1623 if (ds_get_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY) == 2 && cp > tempbuf) { | |
| 1624 char modbuf[256]; | |
| 1625 char *mod = module_name(subtree->modid, modbuf); | |
| 1626 size_t len = strlen(mod); | |
| 1627 if ((int)len+1 >= cp-tempbuf) { | |
| 1628 memmove(tempbuf+len+2, cp, strlen(cp)+1); | |
| 1629 cp = tempbuf+len+2; | |
| 1630 } | |
| 1631 cp -= len+2; | |
| 1632 memcpy(cp, mod, len); | |
| 1633 cp[len] = ':'; | |
| 1634 cp[len+1] = ':'; | |
| 1635 } | |
| 1636 } | |
| 1637 else if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_FULL_OID)) { | |
| 1638 PrefixListPtr pp = &mib_prefixes[0]; | |
| 1639 int ii; | |
| 1640 size_t ilen, tlen; | |
| 1641 const char *testcp; | |
| 1642 cp = tempbuf; tlen = strlen(tempbuf); | |
| 1643 ii = 0; | |
| 1644 while (pp->str) { | |
| 1645 ilen = pp->len; testcp = pp->str; | |
| 1646 if ((tlen > ilen) && !memcmp(tempbuf, testcp, ilen)) { | |
| 1647 cp += (ilen + 1); | |
| 1648 break; | |
| 1649 } | |
| 1650 pp++; | |
| 1651 } | |
| 1652 } | |
| 1653 else cp = tempbuf; | |
| 1654 strcpy(buf, cp); | |
| 1655 return subtree; | |
| 1656 } | |
| 1657 | |
| 1658 char * sprint_objid(char *buf, oid *objid, size_t objidlen) | |
| 1659 { | |
| 1660 _sprint_objid(buf,objid,objidlen); | |
| 1661 return buf; | |
| 1662 } | |
| 1663 | |
| 1664 void | |
| 1665 print_objid(oid *objid, | |
| 1666 size_t objidlen) /* number of subidentifiers */ | |
| 1667 { | |
| 1668 fprint_objid(stdout, objid, objidlen); | |
| 1669 } | |
| 1670 | |
| 1671 void | |
| 1672 fprint_objid(FILE *f, | |
| 1673 oid *objid, | |
| 1674 size_t objidlen) /* number of subidentifiers */ | |
| 1675 { | |
| 1676 char buf[SPRINT_MAX_LEN]; | |
| 1677 | |
| 1678 _sprint_objid(buf, objid, objidlen); | |
| 1679 fprintf(f, "%s\n", buf); | |
| 1680 } | |
| 1681 | |
| 1682 void | |
| 1683 sprint_variable(char *buf, | |
| 1684 oid *objid, | |
| 1685 size_t objidlen, | |
| 1686 struct variable_list *variable) | |
| 1687 { | |
| 1688 struct tree *subtree; | |
| 1689 | |
| 1690 subtree = _sprint_objid(buf, objid, objidlen); | |
| 1691 buf += strlen(buf); | |
| 1692 if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT)) | |
| 1693 strcat(buf, " "); | |
| 1694 else | |
| 1695 strcat(buf, " = "); | |
| 1696 buf += strlen(buf); | |
| 1697 | |
| 1698 if (variable->type == SNMP_NOSUCHOBJECT) | |
| 1699 strcpy(buf, "No Such Object available on this agent"); | |
| 1700 else if (variable->type == SNMP_NOSUCHINSTANCE) | |
| 1701 strcpy(buf, "No Such Instance currently exists"); | |
| 1702 else if (variable->type == SNMP_ENDOFMIBVIEW) | |
| 1703 strcpy(buf, "No more variables left in this MIB View"); | |
| 1704 else if (subtree) { | |
| 1705 if (subtree->printer) | |
| 1706 (*subtree->printer)(buf, variable, subtree->enums, subtree->hint, subtree->units); | |
| 1707 else { | |
| 1708 sprint_by_type(buf, variable, subtree->enums, subtree->hint, subtree->units); | |
| 1709 } | |
| 1710 } | |
| 1711 else { /* handle rare case where tree is empty */ | |
| 1712 sprint_by_type(buf, variable, 0, 0, 0); | |
| 1713 } | |
| 1714 } | |
| 1715 | |
| 1716 void | |
| 1717 print_variable(oid *objid, | |
| 1718 size_t objidlen, | |
| 1719 struct variable_list *variable) | |
| 1720 { | |
| 1721 fprint_variable(stdout, objid, objidlen, variable); | |
| 1722 } | |
| 1723 | |
| 1724 void | |
| 1725 fprint_variable(FILE *f, | |
| 1726 oid *objid, | |
| 1727 size_t objidlen, | |
| 1728 struct variable_list *variable) | |
| 1729 { | |
| 1730 char buf[SPRINT_MAX_LEN]; | |
| 1731 | |
| 1732 sprint_variable(buf, objid, objidlen, variable); | |
| 1733 fprintf(f, "%s\n", buf); | |
| 1734 } | |
| 1735 | |
| 1736 void | |
| 1737 sprint_value(char *buf, | |
| 1738 oid *objid, | |
| 1739 size_t objidlen, | |
| 1740 struct variable_list *variable) | |
| 1741 { | |
| 1742 char tempbuf[SPRINT_MAX_LEN]; | |
| 1743 struct tree *subtree = tree_head; | |
| 1744 | |
| 1745 if (variable->type == SNMP_NOSUCHOBJECT) | |
| 1746 sprintf(buf, "No Such Object available on this agent"); | |
| 1747 else if (variable->type == SNMP_NOSUCHINSTANCE) | |
| 1748 sprintf(buf, "No Such Instance currently exists"); | |
| 1749 else if (variable->type == SNMP_ENDOFMIBVIEW) | |
| 1750 sprintf(buf, "No more variables left in this MIB View"); | |
| 1751 else { | |
| 1752 subtree = get_symbol(objid, objidlen, subtree, tempbuf); | |
| 1753 if (subtree->printer) | |
| 1754 (*subtree->printer)(buf, variable, subtree->enums, subtree->hint, subtree->units); | |
| 1755 else { | |
| 1756 sprint_by_type(buf, variable, subtree->enums, subtree->hint, subtree->units); | |
| 1757 } | |
| 1758 } | |
| 1759 } | |
| 1760 | |
| 1761 void | |
| 1762 print_value(oid *objid, | |
| 1763 size_t objidlen, | |
| 1764 struct variable_list *variable) | |
| 1765 { | |
| 1766 fprint_value(stdout, objid, objidlen, variable); | |
| 1767 } | |
| 1768 | |
| 1769 void | |
| 1770 fprint_value(FILE *f, | |
| 1771 oid *objid, | |
| 1772 size_t objidlen, | |
| 1773 struct variable_list *variable) | |
| 1774 { | |
| 1775 char tempbuf[SPRINT_MAX_LEN]; | |
| 1776 | |
| 1777 sprint_value(tempbuf, objid, objidlen, variable); | |
| 1778 fprintf(f, "%s\n", tempbuf); | |
| 1779 } | |
| 1780 | |
| 1781 | |
| 1782 /* | |
| 1783 * Append a quoted printable string to buffer "buf" | |
| 1784 * that represents a range of sub-identifiers "objid". | |
| 1785 * | |
| 1786 * Display '.' for all non-printable sub-identifiers. | |
| 1787 * If successful, "buf" points past the appended string. | |
| 1788 */ | |
| 1789 char * | |
| 1790 dump_oid_to_string(oid *objid, | |
| 1791 size_t objidlen, | |
| 1792 char *buf, | |
| 1793 char quotechar) | |
| 1794 { | |
| 1795 if (buf) | |
| 1796 { int ii, alen; | |
| 1797 char *scp; | |
| 1798 char *cp = buf + (strlen(buf)); | |
| 1799 scp = cp; | |
| 1800 for (ii= 0, alen = 0; ii < (int)objidlen; ii++) | |
| 1801 { | |
| 1802 oid tst = objid[ii]; | |
| 1803 if ((tst > 254) || (!isprint(tst))) | |
| 1804 tst = (oid)'.'; | |
| 1805 | |
| 1806 if (alen == 0) *cp++ = quotechar; | |
| 1807 *cp++ = (char)tst; | |
| 1808 alen++; | |
| 1809 } | |
| 1810 if (alen) *cp++ = quotechar; | |
| 1811 *cp = '\0'; | |
| 1812 buf = cp; | |
| 1813 } | |
| 1814 | |
| 1815 return buf; | |
| 1816 } | |
| 1817 | |
| 1818 struct tree * | |
| 1819 _get_symbol(oid *objid, | |
| 1820 size_t objidlen, | |
| 1821 struct tree *subtree, | |
| 1822 char *buf, | |
| 1823 struct index_list *in_dices, | |
| 1824 char **end_of_known) | |
| 1825 { | |
| 1826 struct tree *return_tree = NULL; | |
| 1827 | |
| 1828 if (!objid || !buf) | |
| 1829 return NULL; | |
| 1830 | |
| 1831 for(; subtree; subtree = subtree->next_peer){ | |
| 1832 if (*objid == subtree->subid){ | |
| 1833 if (subtree->indexes) | |
| 1834 in_dices = subtree->indexes; | |
| 1835 if (!strncmp( subtree->label, ANON, ANON_LEN) || | |
| 1836 ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_OIDS)) | |
| 1837 sprintf(buf, "%lu", subtree->subid); | |
| 1838 else | |
| 1839 strcpy(buf, subtree->label); | |
| 1840 goto found; | |
| 1841 } | |
| 1842 } | |
| 1843 | |
| 1844 if (end_of_known) | |
| 1845 *end_of_known = buf; | |
| 1846 | |
| 1847 /* subtree not found */ | |
| 1848 | |
| 1849 while (in_dices && (objidlen > 0) && | |
| 1850 !ds_get_boolean(DS_LIBRARY_ID,DS_LIB_PRINT_NUMERIC_OIDS) && | |
| 1851 !ds_get_boolean(DS_LIBRARY_ID,DS_LIB_DONT_BREAKDOWN_OIDS)) { | |
| 1852 size_t numids; | |
| 1853 struct tree *tp; | |
| 1854 tp = find_tree_node(in_dices->ilabel, -1); | |
| 1855 if (0 == tp) { | |
| 1856 /* ack. Can't find an index in the mib tree. bail */ | |
| 1857 goto finish_it; | |
| 1858 } | |
| 1859 switch(tp->type) { | |
| 1860 case TYPE_OCTETSTR: | |
| 1861 if (in_dices->isimplied) { | |
| 1862 numids = objidlen; | |
| 1863 buf = dump_oid_to_string(objid, numids, buf, '\''); | |
| 1864 } else { | |
| 1865 numids = (size_t)*objid+1; | |
| 1866 if (numids > objidlen) | |
| 1867 goto finish_it; | |
| 1868 if (numids == 1) { | |
| 1869 *buf++ = '"'; *buf++ = '"'; | |
| 1870 } | |
| 1871 else | |
| 1872 buf = dump_oid_to_string(objid+1, numids-1, buf, '"'); | |
| 1873 } | |
| 1874 objid += (numids); | |
| 1875 objidlen -= (numids); | |
| 1876 *buf++ = '.'; | |
| 1877 *buf = '\0'; | |
| 1878 break; | |
| 1879 case TYPE_INTEGER: | |
| 1880 sprintf(buf, "%lu.", *objid++); | |
| 1881 while(*buf) | |
| 1882 buf++; | |
| 1883 objidlen--; | |
| 1884 break; | |
| 1885 case TYPE_OBJID: | |
| 1886 if (in_dices->isimplied) { | |
| 1887 numids = objidlen; | |
| 1888 } else { | |
| 1889 numids = (size_t)*objid+1; | |
| 1890 } | |
| 1891 if ( numids > objidlen) | |
| 1892 goto finish_it; | |
| 1893 _get_symbol(objid, numids, NULL, buf, NULL, NULL); | |
| 1894 objid += (numids); | |
| 1895 objidlen -= (numids); | |
| 1896 buf += strlen(buf); | |
| 1897 *buf++ = '.'; | |
| 1898 *buf = '\0'; | |
| 1899 break; | |
| 1900 default: | |
| 1901 goto finish_it; | |
| 1902 break; | |
| 1903 } | |
| 1904 in_dices = in_dices->next; | |
| 1905 } | |
| 1906 | |
| 1907 finish_it: | |
| 1908 | |
| 1909 while(objidlen-- > 0){ /* output rest of name, uninterpreted */ | |
| 1910 sprintf(buf, "%lu.", *objid++); | |
| 1911 while(*buf) | |
| 1912 buf++; | |
| 1913 } | |
| 1914 *(buf - 1) = '\0'; /* remove trailing dot */ | |
| 1915 return NULL; | |
| 1916 | |
| 1917 found: | |
| 1918 if (objidlen > 1){ | |
| 1919 while(*buf) | |
| 1920 buf++; | |
| 1921 *buf++ = '.'; | |
| 1922 *buf = '\0'; | |
| 1923 | |
| 1924 return_tree = _get_symbol(objid + 1, objidlen - 1, subtree->child_list, | |
| 1925 buf, in_dices, end_of_known); | |
| 1926 } | |
| 1927 if (return_tree != NULL) | |
| 1928 return return_tree; | |
| 1929 else | |
| 1930 return subtree; | |
| 1931 } | |
| 1932 | |
| 1933 struct tree * | |
| 1934 get_symbol(oid *objid, | |
| 1935 size_t objidlen, | |
| 1936 struct tree *subtree, | |
| 1937 char *buf) | |
| 1938 { | |
| 1939 return _get_symbol(objid,objidlen,subtree,buf,0,0); | |
| 1940 } | |
| 1941 | |
| 1942 /* | |
| 1943 * Clone of get_symbol that doesn't take a buffer argument | |
| 1944 */ | |
| 1945 struct tree * | |
| 1946 get_tree(oid *objid, | |
| 1947 size_t objidlen, | |
| 1948 struct tree *subtree) | |
| 1949 { | |
| 1950 struct tree *return_tree = NULL; | |
| 1951 | |
| 1952 for(; subtree; subtree = subtree->next_peer){ | |
| 1953 if (*objid == subtree->subid) | |
| 1954 goto found; | |
| 1955 } | |
| 1956 | |
| 1957 return NULL; | |
| 1958 | |
| 1959 found: | |
| 1960 if (objidlen > 1) | |
| 1961 return_tree = get_tree(objid + 1, objidlen - 1, subtree->child_list); | |
| 1962 if (return_tree != NULL) | |
| 1963 return return_tree; | |
| 1964 else | |
| 1965 return subtree; | |
| 1966 } | |
| 1967 | |
| 1968 void | |
| 1969 print_description(oid *objid, | |
| 1970 size_t objidlen) /* number of subidentifiers */ | |
| 1971 { | |
| 1972 fprint_description(stdout, objid, objidlen); | |
| 1973 } | |
| 1974 | |
| 1975 void | |
| 1976 fprint_description(FILE *f, | |
| 1977 oid *objid, | |
| 1978 size_t objidlen) /* number of subidentifiers */ | |
| 1979 { | |
| 1980 struct tree *tp = get_tree(objid, objidlen, tree_head); | |
| 1981 struct tree *subtree = tree_head; | |
| 1982 fprintf(f, "%s OBJECT-TYPE\n", tp->label); | |
| 1983 print_tree_node(f, tp); | |
| 1984 fprintf(f, "::= {"); | |
| 1985 while (objidlen > 1) { | |
| 1986 for(; subtree; subtree = subtree->next_peer){ | |
| 1987 if (*objid == subtree->subid){ | |
| 1988 if (strncmp( subtree->label, ANON, ANON_LEN)) | |
| 1989 fprintf(f, " %s(%lu)", subtree->label, subtree->subid); | |
| 1990 else | |
| 1991 fprintf(f, " %lu", subtree->subid); | |
| 1992 break; | |
| 1993 } | |
| 1994 } | |
| 1995 if (subtree == 0) break; | |
| 1996 objid++; objidlen--; subtree = subtree->child_list; | |
| 1997 if (subtree == 0) break; | |
| 1998 } | |
| 1999 fprintf(f, " %lu }\n", *objid); | |
| 2000 } | |
| 2001 | |
| 2002 void | |
| 2003 print_tree_node(FILE *f, | |
| 2004 struct tree *tp) | |
| 2005 { | |
| 2006 const char *cp; | |
| 2007 char str[MAXTOKEN]; | |
| 2008 int i, prevmod; | |
| 2009 if (tp) { | |
| 2010 module_name(tp->modid, str); | |
| 2011 fprintf(f, " -- FROM\t%s", str); | |
| 2012 for (i = 1, prevmod = tp->modid; i < tp->number_modules; i++) { | |
| 2013 if (prevmod != tp->module_list[i]) { | |
| 2014 module_name(tp->module_list[i], str); | |
| 2015 fprintf(f, ", %s", str); | |
| 2016 } | |
| 2017 prevmod = tp->module_list[i]; | |
| 2018 } | |
| 2019 fprintf(f, "\n"); | |
| 2020 if (tp->tc_index != -1) { | |
| 2021 fprintf(f, " -- TEXTUAL CONVENTION %s\n", get_tc_descriptor(tp->tc_index)); | |
| 2022 } | |
| 2023 switch (tp->type) { | |
| 2024 case TYPE_OBJID: cp = "OBJECT IDENTIFIER"; break; | |
| 2025 case TYPE_OCTETSTR: cp = "OCTET STRING"; break; | |
| 2026 case TYPE_INTEGER: cp = "INTEGER"; break; | |
| 2027 case TYPE_NETADDR: cp = "NetworkAddress"; break; | |
| 2028 case TYPE_IPADDR: cp = "IpAddress"; break; | |
| 2029 case TYPE_COUNTER: cp = "Counter"; break; | |
| 2030 case TYPE_GAUGE: cp = "Gauge"; break; | |
| 2031 case TYPE_TIMETICKS: cp = "TimeTicks"; break; | |
| 2032 case TYPE_OPAQUE: cp = "Opaque"; break; | |
| 2033 case TYPE_NULL: cp = "NULL"; break; | |
| 2034 case TYPE_COUNTER64: cp = "Counter64"; break; | |
| 2035 case TYPE_BITSTRING: cp = "BIT STRING"; break; | |
| 2036 case TYPE_NSAPADDRESS: cp = "NsapAddress"; break; | |
| 2037 case TYPE_UINTEGER: cp = "UInteger32"; break; | |
| 2038 case 0: cp = NULL; break; | |
| 2039 default: sprintf(str,"type_%d", tp->type); cp = str; | |
| 2040 } | |
| 2041 #if SNMP_TESTING_CODE | |
| 2042 if (!cp && (tp->ranges || tp->enums)) { /* ranges without type ? */ | |
| 2043 sprintf(str,"?0 with %s %s ?", | |
| 2044 tp->ranges ? "Range" : "", | |
| 2045 tp->enums ? "Enum" : ""); | |
| 2046 cp = str; | |
| 2047 } | |
| 2048 #endif /* SNMP_TESTING_CODE */ | |
| 2049 if (cp) fprintf(f, " SYNTAX\t%s", cp); | |
| 2050 if (tp->ranges) { | |
| 2051 struct range_list *rp = tp->ranges; | |
| 2052 int first = 1; | |
| 2053 fprintf(f, " ("); | |
| 2054 while (rp) { | |
| 2055 if (first) first = 0; | |
| 2056 else fprintf(f, " | "); | |
| 2057 if (rp->low == rp->high) fprintf(f, "%d", rp->low); | |
| 2058 else fprintf(f, "%d..%d", rp->low, rp->high); | |
| 2059 rp = rp->next; | |
| 2060 } | |
| 2061 fprintf(f, ") "); | |
| 2062 } | |
| 2063 if (tp->enums) { | |
| 2064 struct enum_list *ep = tp->enums; | |
| 2065 int first = 1; | |
| 2066 fprintf(f," { "); | |
| 2067 while (ep) { | |
| 2068 if (first) first = 0; | |
| 2069 else fprintf(f, ", "); | |
| 2070 fprintf(f, "%s(%d)", ep->label, ep->value); | |
| 2071 ep = ep->next; | |
| 2072 } | |
| 2073 fprintf(f," } "); | |
| 2074 } | |
| 2075 if (cp) fprintf(f, "\n"); | |
| 2076 if (tp->hint) fprintf(f, " DISPLAY-HINT\t\"%s\"\n", tp->hint); | |
| 2077 if (tp->units) fprintf(f, " UNITS\t\"%s\"\n", tp->units); | |
| 2078 switch (tp->access) { | |
| 2079 case MIB_ACCESS_READONLY: cp = "read-only"; break; | |
| 2080 case MIB_ACCESS_READWRITE: cp = "read-write"; break; | |
| 2081 case MIB_ACCESS_WRITEONLY: cp = "write-only"; break; | |
| 2082 case MIB_ACCESS_NOACCESS: cp = "not-accessible"; break; | |
| 2083 case MIB_ACCESS_NOTIFY: cp = "accessible-for-notify"; break; | |
| 2084 case MIB_ACCESS_CREATE: cp = "read-create"; break; | |
| 2085 case 0: cp = NULL; break; | |
| 2086 default: sprintf(str,"access_%d", tp->access); cp = str; | |
| 2087 } | |
| 2088 if (cp) fprintf(f, " MAX-ACCESS\t%s\n", cp); | |
| 2089 switch (tp->status) { | |
| 2090 case MIB_STATUS_MANDATORY: cp = "mandatory"; break; | |
| 2091 case MIB_STATUS_OPTIONAL: cp = "optional"; break; | |
| 2092 case MIB_STATUS_OBSOLETE: cp = "obsolete"; break; | |
| 2093 case MIB_STATUS_DEPRECATED: cp = "deprecated"; break; | |
| 2094 case MIB_STATUS_CURRENT: cp = "current"; break; | |
| 2095 case 0: cp = NULL; break; | |
| 2096 default: sprintf(str,"status_%d", tp->status); cp = str; | |
| 2097 } | |
| 2098 #if SNMP_TESTING_CODE | |
| 2099 if (!cp && (tp->indexes)) { /* index without status ? */ | |
| 2100 sprintf(str,"?0 with %s ?", | |
| 2101 tp->indexes ? "Index" : ""); | |
| 2102 cp = str; | |
| 2103 } | |
| 2104 #endif /* SNMP_TESTING_CODE */ | |
| 2105 if (cp) fprintf(f, " STATUS\t%s\n", cp); | |
| 2106 if (tp->indexes) { | |
| 2107 struct index_list *ip = tp->indexes; | |
| 2108 int first=1; | |
| 2109 fprintf(f, " INDEXES\t"); | |
| 2110 fprintf(f," { "); | |
| 2111 while (ip) { | |
| 2112 if (first) first = 0; | |
| 2113 else fprintf(f, ", "); | |
| 2114 if (ip->isimplied) | |
| 2115 fprintf(f, "IMPLIED "); | |
| 2116 fprintf(f, "%s", ip->ilabel); | |
| 2117 ip = ip->next; | |
| 2118 } | |
| 2119 fprintf(f," }\n"); | |
| 2120 } | |
| 2121 if (tp->description) fprintf(f, " DESCRIPTION\t\"%s\"\n", tp->description); | |
| 2122 } | |
| 2123 else | |
| 2124 fprintf(f, "No description\n"); | |
| 2125 } | |
| 2126 | |
| 2127 int | |
| 2128 get_module_node(const char *fname, | |
| 2129 const char *module, | |
| 2130 oid *objid, | |
| 2131 size_t *objidlen) | |
| 2132 { | |
| 2133 int modid, rc = 0; | |
| 2134 struct tree *tp; | |
| 2135 char *name, *cp; | |
| 2136 | |
| 2137 if ( !strcmp(module, "ANY") ) | |
| 2138 modid = -1; | |
| 2139 else { | |
| 2140 read_module(module); | |
| 2141 modid = which_module( module ); | |
| 2142 if (modid == -1) return 0; | |
| 2143 } | |
| 2144 | |
| 2145 /* Isolate the first component of the name ... */ | |
| 2146 name = strdup(fname); | |
| 2147 cp = strchr( name, '.' ); | |
| 2148 if ( cp != NULL ) { | |
| 2149 *cp = '\0'; | |
| 2150 cp++; | |
| 2151 } | |
| 2152 /* ... and locate it in the tree. */ | |
| 2153 tp = find_tree_node(name, modid); | |
| 2154 if (tp){ | |
| 2155 size_t maxlen = *objidlen; | |
| 2156 | |
| 2157 /* Set the first element of the object ID */ | |
| 2158 if (node_to_oid(tp, objid, objidlen)) { | |
| 2159 rc = 1; | |
| 2160 | |
| 2161 /* If the name requested was more than one element, | |
| 2162 tag on the rest of the components */ | |
| 2163 if (cp != NULL) | |
| 2164 rc = _add_strings_to_oid(tp, cp, objid, objidlen, maxlen); | |
| 2165 } | |
| 2166 } | |
| 2167 | |
| 2168 free(name); | |
| 2169 return (rc); | |
| 2170 } | |
| 2171 | |
| 2172 | |
| 2173 /* | |
| 2174 * Populate object identifier from a node in the MIB hierarchy. | |
| 2175 * Build up the object ID, working backwards, | |
| 2176 * starting from the end of the objid buffer. | |
| 2177 * When the top of the MIB tree is reached, adjust the buffer. | |
| 2178 * | |
| 2179 * The buffer length is set to the number of subidentifiers | |
| 2180 * for the object identifier associated with the MIB node. | |
| 2181 * Returns the number of subidentifiers copied. | |
| 2182 * | |
| 2183 * If 0 is returned, the objid buffer is too small, | |
| 2184 * and the buffer contents are indeterminate. | |
| 2185 * The buffer length can be used to create a larger buffer. | |
| 2186 */ | |
| 2187 int | |
| 2188 node_to_oid(struct tree *tp, oid *objid, size_t *objidlen) | |
| 2189 { | |
| 2190 int numids, lenids; | |
| 2191 oid *op; | |
| 2192 | |
| 2193 if (!tp || !objid || !objidlen) | |
| 2194 return 0; | |
| 2195 | |
| 2196 lenids = (int)*objidlen; | |
| 2197 op = objid + lenids; /* points after the last element */ | |
| 2198 | |
| 2199 for(numids = 0; tp; tp = tp->parent, numids++) | |
| 2200 { | |
| 2201 if (numids >= lenids) continue; | |
| 2202 --op; | |
| 2203 *op = tp->subid; | |
| 2204 } | |
| 2205 | |
| 2206 *objidlen = (size_t)numids; | |
| 2207 if (numids > lenids) { | |
| 2208 return 0; | |
| 2209 } | |
| 2210 | |
| 2211 if (numids < lenids) | |
| 2212 memmove(objid, op, numids * sizeof(oid)); | |
| 2213 | |
| 2214 return (numids); | |
| 2215 } | |
| 2216 | |
| 2217 static int | |
| 2218 _add_strings_to_oid(struct tree *tp, char *cp, | |
| 2219 oid *objid, size_t *objidlen, | |
| 2220 size_t maxlen) | |
| 2221 { | |
| 2222 int subid; | |
| 2223 struct tree *tp2 = NULL; | |
| 2224 char *cp2 = NULL; | |
| 2225 char doingquote = 0; | |
| 2226 | |
| 2227 while ( cp != NULL ) { | |
| 2228 cp2 = strchr( cp, '.' ); /* Isolate the next entry */ | |
| 2229 if ( cp2 != NULL ) { | |
| 2230 *cp2 = '\0'; | |
| 2231 cp2++; | |
| 2232 } | |
| 2233 | |
| 2234 if ( *cp == '"' || *cp == '\'') { /* Is it the beggining | |
| 2235 of a quoted string */ | |
| 2236 doingquote = *cp++; | |
| 2237 /* insert length if requested */ | |
| 2238 if (doingquote == '"') { | |
| 2239 if (*objidlen >= maxlen) | |
| 2240 return 0; | |
| 2241 objid[ *objidlen ] = (strchr(cp,doingquote) - cp); | |
| 2242 (*objidlen)++; | |
| 2243 } | |
| 2244 | |
| 2245 while(*cp != doingquote) { | |
| 2246 if (*objidlen >= maxlen) | |
| 2247 return 0; | |
| 2248 objid[ *objidlen ] = *cp++; | |
| 2249 (*objidlen)++; | |
| 2250 } | |
| 2251 | |
| 2252 tp = NULL; /* must be pure numeric from here, right? */ | |
| 2253 cp = cp2; | |
| 2254 continue; | |
| 2255 } | |
| 2256 | |
| 2257 /* Is it numeric ? */ | |
| 2258 if ( isdigit( *cp ) ) | |
| 2259 subid=(strtol(cp,0,0)); | |
| 2260 else | |
| 2261 subid = -1; | |
| 2262 | |
| 2263 /* Search for the appropriate child */ | |
| 2264 if ( tp != NULL ) | |
| 2265 tp2 = tp->child_list; | |
| 2266 while ( tp2 != NULL ) { | |
| 2267 if (( (int)tp2->subid == subid ) || | |
| 2268 ( !strcasecmp( tp2->label, cp ))) { | |
| 2269 if (*objidlen >= maxlen) | |
| 2270 return 0; | |
| 2271 objid[ *objidlen ] = tp2->subid; | |
| 2272 (*objidlen)++; | |
| 2273 tp = tp2; | |
| 2274 break; | |
| 2275 } | |
| 2276 tp2 = tp2->next_peer; | |
| 2277 } | |
| 2278 if ( tp2 == NULL ) { | |
| 2279 if ( subid == -1 ) { | |
| 2280 return 0; | |
| 2281 } | |
| 2282 /* pure numeric from now on */ | |
| 2283 if (*objidlen >= maxlen) | |
| 2284 return 0; | |
| 2285 objid[ *objidlen ] = subid; | |
| 2286 (*objidlen)++; | |
| 2287 tp = NULL; | |
| 2288 } | |
| 2289 cp = cp2; | |
| 2290 } | |
| 2291 | |
| 2292 return 1; | |
| 2293 } | |
| 2294 | |
| 2295 | |
| 2296 /* | |
| 2297 * see comments on find_best_tree_node for usage after first time. | |
| 2298 */ | |
| 2299 int | |
| 2300 get_wild_node(const char *name, | |
| 2301 oid *objid, | |
| 2302 size_t *objidlen) | |
| 2303 { | |
| 2304 struct tree *tp = find_best_tree_node(name, tree_head, NULL); | |
| 2305 if (!tp) | |
| 2306 return 0; | |
| 2307 return get_node(tp->label, objid, objidlen); | |
| 2308 } | |
| 2309 | |
| 2310 int | |
| 2311 get_node(const char *name, | |
| 2312 oid *objid, | |
| 2313 size_t *objidlen) | |
| 2314 { | |
| 2315 char *cp; | |
| 2316 int res; | |
| 2317 | |
| 2318 if (( cp=strchr(name, ':')) == NULL ) | |
| 2319 res = get_module_node( name, "ANY", objid, objidlen ); | |
| 2320 else { | |
| 2321 char *module; | |
| 2322 /* | |
| 2323 * requested name is of the form | |
| 2324 * "module:subidentifier" | |
| 2325 */ | |
| 2326 module = (char *)malloc((size_t)(cp-name+1)); | |
| 2327 memcpy(module,name,(size_t)(cp-name)); | |
| 2328 module[cp-name] = 0; | |
| 2329 cp++; /* cp now point to the subidentifier */ | |
| 2330 if (*cp == ':') cp++; | |
| 2331 | |
| 2332 /* 'cp' and 'name' *do* go that way round! */ | |
| 2333 res = get_module_node( cp, module, objid, objidlen ); | |
| 2334 free(module); | |
| 2335 } | |
| 2336 if (res == 0) { | |
| 2337 SET_SNMP_ERROR(SNMPERR_UNKNOWN_OBJID); | |
| 2338 } | |
| 2339 | |
| 2340 return res; | |
| 2341 } | |
| 2342 | |
| 2343 #ifdef testing | |
| 2344 | |
| 2345 main(int argc, char* argv[]) | |
| 2346 { | |
| 2347 oid objid[MAX_OID_LEN]; | |
| 2348 int objidlen = MAX_OID_LEN; | |
| 2349 int count; | |
| 2350 struct variable_list variable; | |
| 2351 | |
| 2352 init_mib(); | |
| 2353 if (argc < 2) | |
| 2354 print_subtree(stdout, tree_head, 0); | |
| 2355 variable.type = ASN_INTEGER; | |
| 2356 variable.val.integer = 3; | |
| 2357 variable.val_len = 4; | |
| 2358 for (argc--; argc; argc--, argv++) { | |
| 2359 objidlen = MAX_OID_LEN; | |
| 2360 printf("read_objid(%s) = %d\n", | |
| 2361 argv[1], read_objid(argv[1], objid, &objidlen)); | |
| 2362 for(count = 0; count < objidlen; count++) | |
| 2363 printf("%d.", objid[count]); | |
| 2364 printf("\n"); | |
| 2365 print_variable(objid, objidlen, &variable); | |
| 2366 } | |
| 2367 } | |
| 2368 | |
| 2369 #endif /* testing */ | |
| 2370 | |
| 2371 /* initialize: no peers included in the report. */ | |
| 2372 void clear_tree_flags(register struct tree *tp) | |
| 2373 { | |
| 2374 for (; tp; tp = tp->next_peer) | |
| 2375 { | |
| 2376 tp->reported = 0; | |
| 2377 if (tp->child_list) | |
| 2378 clear_tree_flags(tp->child_list); /*RECURSE*/ | |
| 2379 } | |
| 2380 } | |
| 2381 | |
| 2382 /* | |
| 2383 * Update: 1998-07-17 <jhy@gsu.edu> | |
| 2384 * Added print_oid_report* functions. | |
| 2385 */ | |
| 2386 static int print_subtree_oid_report_labeledoid = 0; | |
| 2387 static int print_subtree_oid_report_oid = 0; | |
| 2388 static int print_subtree_oid_report_symbolic = 0; | |
| 2389 static int print_subtree_oid_report_suffix = 0; | |
| 2390 | |
| 2391 /* These methods recurse. */ | |
| 2392 static void print_parent_labeledoid(FILE *, struct tree *); | |
| 2393 static void print_parent_oid(FILE *, struct tree *); | |
| 2394 static void print_parent_label(FILE *, struct tree *); | |
| 2395 static void print_subtree_oid_report(FILE *, struct tree *, int); | |
| 2396 | |
| 2397 | |
| 2398 void | |
| 2399 print_oid_report (FILE *fp) | |
| 2400 { | |
| 2401 struct tree *tp; | |
| 2402 clear_tree_flags(tree_head); | |
| 2403 for (tp = tree_head ; tp ; tp=tp->next_peer) | |
| 2404 print_subtree_oid_report (fp, tp, 0); | |
| 2405 } | |
| 2406 | |
| 2407 void | |
| 2408 print_oid_report_enable_labeledoid (void) | |
| 2409 { | |
| 2410 print_subtree_oid_report_labeledoid = 1; | |
| 2411 } | |
| 2412 | |
| 2413 void | |
| 2414 print_oid_report_enable_oid (void) | |
| 2415 { | |
| 2416 print_subtree_oid_report_oid = 1; | |
| 2417 } | |
| 2418 | |
| 2419 void | |
| 2420 print_oid_report_enable_suffix (void) | |
| 2421 { | |
| 2422 print_subtree_oid_report_suffix = 1; | |
| 2423 } | |
| 2424 | |
| 2425 void | |
| 2426 print_oid_report_enable_symbolic (void) | |
| 2427 { | |
| 2428 print_subtree_oid_report_symbolic = 1; | |
| 2429 } | |
| 2430 | |
| 2431 /* | |
| 2432 * helper methods for print_subtree_oid_report() | |
| 2433 * each one traverses back up the node tree | |
| 2434 * until there is no parent. Then, the label combination | |
| 2435 * is output, such that the parent is displayed first. | |
| 2436 * | |
| 2437 * Warning: these methods are all recursive. | |
| 2438 */ | |
| 2439 | |
| 2440 static void | |
| 2441 print_parent_labeledoid(FILE *f, | |
| 2442 struct tree *tp) | |
| 2443 { | |
| 2444 if(tp) | |
| 2445 { | |
| 2446 if(tp->parent) | |
| 2447 { | |
| 2448 print_parent_labeledoid(f, tp->parent); /*RECURSE*/ | |
| 2449 } | |
| 2450 fprintf(f, ".%s(%lu)", tp->label, tp->subid); | |
| 2451 } | |
| 2452 } | |
| 2453 | |
| 2454 static void | |
| 2455 print_parent_oid(FILE *f, | |
| 2456 struct tree *tp) | |
| 2457 { | |
| 2458 if(tp) | |
| 2459 { | |
| 2460 if(tp->parent) | |
| 2461 { | |
| 2462 print_parent_oid(f, tp->parent); /*RECURSE*/ | |
| 2463 } | |
| 2464 fprintf(f, ".%lu", tp->subid); | |
| 2465 } | |
| 2466 } | |
| 2467 | |
| 2468 static void | |
| 2469 print_parent_label(FILE *f, | |
| 2470 struct tree *tp) | |
| 2471 { | |
| 2472 if(tp) | |
| 2473 { | |
| 2474 if(tp->parent) | |
| 2475 { | |
| 2476 print_parent_label(f, tp->parent); /*RECURSE*/ | |
| 2477 } | |
| 2478 fprintf(f, ".%s", tp->label); | |
| 2479 } | |
| 2480 } | |
| 2481 | |
| 2482 /* | |
| 2483 * print_subtree_oid_report(): | |
| 2484 * | |
| 2485 * This methods generates variations on the original print_subtree() report. | |
| 2486 * Traverse the tree depth first, from least to greatest sub-identifier. | |
| 2487 * Warning: this methods recurses and calls methods that recurse. | |
| 2488 */ | |
| 2489 | |
| 2490 static void | |
| 2491 print_subtree_oid_report(FILE *f, | |
| 2492 struct tree *tree, | |
| 2493 int count) | |
| 2494 { | |
| 2495 struct tree *tp; | |
| 2496 | |
| 2497 count++; | |
| 2498 | |
| 2499 /* sanity check */ | |
| 2500 if(!tree) | |
| 2501 { | |
| 2502 return; | |
| 2503 } | |
| 2504 | |
| 2505 /* | |
| 2506 * find the not reported peer with the lowest sub-identifier. | |
| 2507 * if no more, break the loop and cleanup. | |
| 2508 * set "reported" flag, and create report for this peer. | |
| 2509 * recurse using the children of this peer, if any. | |
| 2510 */ | |
| 2511 while (1) | |
| 2512 { | |
| 2513 register struct tree *ntp; | |
| 2514 | |
| 2515 tp = 0; | |
| 2516 for (ntp = tree->child_list; ntp; ntp = ntp->next_peer) | |
| 2517 { | |
| 2518 if (ntp->reported) continue; | |
| 2519 | |
| 2520 if (!tp || (tp->subid > ntp->subid)) | |
| 2521 tp = ntp; | |
| 2522 } | |
| 2523 if (!tp) break; | |
| 2524 | |
| 2525 tp->reported = 1; | |
| 2526 | |
| 2527 if(print_subtree_oid_report_labeledoid) | |
| 2528 { | |
| 2529 print_parent_labeledoid(f, tp); | |
| 2530 fprintf(f, "\n"); | |
| 2531 } | |
| 2532 if(print_subtree_oid_report_oid) | |
| 2533 { | |
| 2534 print_parent_oid(f, tp); | |
| 2535 fprintf(f, "\n"); | |
| 2536 } | |
| 2537 if(print_subtree_oid_report_symbolic) | |
| 2538 { | |
| 2539 print_parent_label(f, tp); | |
| 2540 fprintf(f, "\n"); | |
| 2541 } | |
| 2542 if(print_subtree_oid_report_suffix) | |
| 2543 { | |
| 2544 int i; | |
| 2545 for(i = 0; i < count; i++) | |
| 2546 fprintf(f, " "); | |
| 2547 fprintf(f, "%s(%ld) type=%d", tp->label, tp->subid, tp->type); | |
| 2548 if (tp->tc_index != -1) fprintf(f, " tc=%d", tp->tc_index); | |
| 2549 if (tp->hint) fprintf(f, " hint=%s", tp->hint); | |
| 2550 if (tp->units) fprintf(f, " units=%s", tp->units); | |
| 2551 | |
| 2552 fprintf(f, "\n"); | |
| 2553 } | |
| 2554 print_subtree_oid_report(f, tp, count); /*RECURSE*/ | |
| 2555 } | |
| 2556 } | |
| 2557 | |
| 2558 | |
| 2559 /* | |
| 2560 * Convert timeticks to hours, minutes, seconds string. | |
| 2561 * CMU compatible does not show centiseconds. | |
| 2562 */ | |
| 2563 char *uptime_string(u_long timeticks, char *buf) | |
| 2564 { | |
| 2565 char tbuf[64]; | |
| 2566 char * cp; | |
| 2567 uptimeString(timeticks, tbuf); | |
| 2568 cp = strrchr(tbuf, '.'); | |
| 2569 #ifdef CMU_COMPATIBLE | |
| 2570 if (cp) *cp = '\0'; | |
| 2571 #endif | |
| 2572 strcpy(buf, tbuf); | |
| 2573 return buf; | |
| 2574 } | |
| 2575 | |
| 2576 #ifdef CMU_COMPATIBLE | |
| 2577 | |
| 2578 int mib_TxtToOid(char *Buf, oid **OidP, size_t *LenP) | |
| 2579 { | |
| 2580 return read_objid(Buf, *OidP, LenP); | |
| 2581 } | |
| 2582 | |
| 2583 int mib_OidToTxt(oid *O, size_t OidLen, char *Buf, size_t BufLen) | |
| 2584 { | |
| 2585 _sprint_objid(Buf, O, OidLen); | |
| 2586 return 1; | |
| 2587 } | |
| 2588 | |
| 2589 #endif /* CMU_COMPATIBLE */ |
