net-snmp
5.4.1
|
00001 /* 00002 * mib.c 00003 * 00004 * $Id: mib.c 16360 2007-05-12 11:14:39Z magfr $ 00005 * 00006 * Update: 1998-07-17 <jhy@gsu.edu> 00007 * Added print_oid_report* functions. 00008 * 00009 */ 00010 /* Portions of this file are subject to the following copyrights. See 00011 * the Net-SNMP's COPYING file for more details and other copyrights 00012 * that may apply: 00013 */ 00014 /********************************************************************** 00015 Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University 00016 00017 All Rights Reserved 00018 00019 Permission to use, copy, modify, and distribute this software and its 00020 documentation for any purpose and without fee is hereby granted, 00021 provided that the above copyright notice appear in all copies and that 00022 both that copyright notice and this permission notice appear in 00023 supporting documentation, and that the name of CMU not be 00024 used in advertising or publicity pertaining to distribution of the 00025 software without specific, written prior permission. 00026 00027 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 00028 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 00029 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 00030 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 00031 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 00032 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 00033 SOFTWARE. 00034 ******************************************************************/ 00035 /* 00036 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. 00037 * Use is subject to license terms specified in the COPYING file 00038 * distributed with the Net-SNMP package. 00039 */ 00040 #include <net-snmp/net-snmp-config.h> 00041 00042 #include <stdio.h> 00043 #include <ctype.h> 00044 #include <sys/types.h> 00045 #if HAVE_NETINET_IN_H 00046 #include <netinet/in.h> 00047 #endif 00048 #if TIME_WITH_SYS_TIME 00049 # ifdef WIN32 00050 # include <sys/timeb.h> 00051 # else 00052 # include <sys/time.h> 00053 # endif 00054 # include <time.h> 00055 #else 00056 # if HAVE_SYS_TIME_H 00057 # include <sys/time.h> 00058 # else 00059 # include <time.h> 00060 # endif 00061 #endif 00062 #if HAVE_STRING_H 00063 #include <string.h> 00064 #else 00065 #include <strings.h> 00066 #endif 00067 #if HAVE_STDLIB_H 00068 #include <stdlib.h> 00069 #endif 00070 #if HAVE_SYS_SELECT_H 00071 #include <sys/select.h> 00072 #endif 00073 00074 #if HAVE_WINSOCK_H 00075 #include <winsock.h> 00076 #endif 00077 00078 #if HAVE_DMALLOC_H 00079 #include <dmalloc.h> 00080 #endif 00081 00082 #include <net-snmp/types.h> 00083 #include <net-snmp/output_api.h> 00084 #include <net-snmp/config_api.h> 00085 #include <net-snmp/utilities.h> 00086 00087 #include <net-snmp/library/asn1.h> 00088 #include <net-snmp/library/snmp_api.h> 00089 #include <net-snmp/library/mib.h> 00090 #include <net-snmp/library/parse.h> 00091 #include <net-snmp/library/int64.h> 00092 #include <net-snmp/library/snmp_client.h> 00093 00100 static char *uptimeString(u_long, char *, size_t); 00101 00102 static struct tree *_get_realloc_symbol(const oid * objid, size_t objidlen, 00103 struct tree *subtree, 00104 u_char ** buf, size_t * buf_len, 00105 size_t * out_len, 00106 int allow_realloc, 00107 int *buf_overflow, 00108 struct index_list *in_dices, 00109 size_t * end_of_known); 00110 00111 static int print_tree_node(u_char ** buf, size_t * buf_len, 00112 size_t * out_len, int allow_realloc, 00113 struct tree *tp, int width); 00114 static void handle_mibdirs_conf(const char *token, char *line); 00115 static void handle_mibs_conf(const char *token, char *line); 00116 static void handle_mibfile_conf(const char *token, char *line); 00117 00118 static void _oid_finish_printing(const oid * objid, size_t objidlen, 00119 u_char ** buf, size_t * buf_len, 00120 size_t * out_len, 00121 int allow_realloc, int *buf_overflow); 00122 00123 /* 00124 * helper functions for get_module_node 00125 */ 00126 static int node_to_oid(struct tree *, oid *, size_t *); 00127 #ifndef NETSNMP_DISABLE_MIB_LOADING 00128 static int _add_strings_to_oid(struct tree *, char *, 00129 oid *, size_t *, size_t); 00130 #else 00131 static int _add_strings_to_oid(void *, char *, 00132 oid *, size_t *, size_t); 00133 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 00134 00135 #ifndef NETSNMP_DISABLE_MIB_LOADING 00136 extern struct tree *tree_head; 00137 static struct tree *tree_top; 00138 00139 struct tree *Mib; /* Backwards compatibility */ 00140 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 00141 00142 oid RFC1213_MIB[] = { 1, 3, 6, 1, 2, 1 }; 00143 static char Standard_Prefix[] = ".1.3.6.1.2.1"; 00144 00145 /* 00146 * Set default here as some uses of read_objid require valid pointer. 00147 */ 00148 static char *Prefix = &Standard_Prefix[0]; 00149 typedef struct _PrefixList { 00150 const char *str; 00151 int len; 00152 } *PrefixListPtr, PrefixList; 00153 00154 /* 00155 * Here are the prefix strings. 00156 * Note that the first one finds the value of Prefix or Standard_Prefix. 00157 * Any of these MAY start with period; all will NOT end with period. 00158 * Period is added where needed. See use of Prefix in this module. 00159 */ 00160 PrefixList mib_prefixes[] = { 00161 {&Standard_Prefix[0]}, /* placeholder for Prefix data */ 00162 {".iso.org.dod.internet.mgmt.mib-2"}, 00163 {".iso.org.dod.internet.experimental"}, 00164 {".iso.org.dod.internet.private"}, 00165 {".iso.org.dod.internet.snmpParties"}, 00166 {".iso.org.dod.internet.snmpSecrets"}, 00167 {NULL, 0} /* end of list */ 00168 }; 00169 00170 enum inet_address_type { 00171 IPV4 = 1, 00172 IPV6 = 2, 00173 IPV4Z = 3, 00174 IPV6Z = 4, 00175 DNS = 16 00176 }; 00177 00178 00189 static char * 00190 uptimeString(u_long timeticks, char *buf, size_t buflen) 00191 { 00192 int centisecs, seconds, minutes, hours, days; 00193 00194 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS)) { 00195 snprintf(buf, buflen, "%lu", timeticks); 00196 return buf; 00197 } 00198 00199 00200 centisecs = timeticks % 100; 00201 timeticks /= 100; 00202 days = timeticks / (60 * 60 * 24); 00203 timeticks %= (60 * 60 * 24); 00204 00205 hours = timeticks / (60 * 60); 00206 timeticks %= (60 * 60); 00207 00208 minutes = timeticks / 60; 00209 seconds = timeticks % 60; 00210 00211 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) 00212 snprintf(buf, buflen, "%d:%d:%02d:%02d.%02d", 00213 days, hours, minutes, seconds, centisecs); 00214 else { 00215 if (days == 0) { 00216 snprintf(buf, buflen, "%d:%02d:%02d.%02d", 00217 hours, minutes, seconds, centisecs); 00218 } else if (days == 1) { 00219 snprintf(buf, buflen, "%d day, %d:%02d:%02d.%02d", 00220 days, hours, minutes, seconds, centisecs); 00221 } else { 00222 snprintf(buf, buflen, "%d days, %d:%02d:%02d.%02d", 00223 days, hours, minutes, seconds, centisecs); 00224 } 00225 } 00226 return buf; 00227 } 00228 00229 00230 00239 static void 00240 sprint_char(char *buf, const u_char ch) 00241 { 00242 if (isprint(ch) || isspace(ch)) { 00243 sprintf(buf, "%c", (int) ch); 00244 } else { 00245 sprintf(buf, "."); 00246 } 00247 } 00248 00249 00250 00270 int 00271 _sprint_hexstring_line(u_char ** buf, size_t * buf_len, size_t * out_len, 00272 int allow_realloc, const u_char * cp, size_t line_len) 00273 { 00274 const u_char *tp; 00275 const u_char *cp2 = cp; 00276 size_t lenleft = line_len; 00277 00278 /* 00279 * Make sure there's enough room for the hex output.... 00280 */ 00281 while ((*out_len + line_len*3+1) >= *buf_len) { 00282 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 00283 return 0; 00284 } 00285 } 00286 00287 /* 00288 * .... and display the hex values themselves.... 00289 */ 00290 for (; lenleft >= 8; lenleft-=8) { 00291 sprintf((char *) (*buf + *out_len), 00292 "%02X %02X %02X %02X %02X %02X %02X %02X ", cp[0], cp[1], 00293 cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); 00294 *out_len += strlen((char *) (*buf + *out_len)); 00295 cp += 8; 00296 } 00297 for (; lenleft > 0; lenleft--) { 00298 sprintf((char *) (*buf + *out_len), "%02X ", *cp++); 00299 *out_len += strlen((char *) (*buf + *out_len)); 00300 } 00301 00302 /* 00303 * .... plus (optionally) do the same for the ASCII equivalent. 00304 */ 00305 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT)) { 00306 while ((*out_len + line_len+5) >= *buf_len) { 00307 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 00308 return 0; 00309 } 00310 } 00311 sprintf((char *) (*buf + *out_len), " ["); 00312 *out_len += strlen((char *) (*buf + *out_len)); 00313 for (tp = cp2; tp < cp; tp++) { 00314 sprint_char((char *) (*buf + *out_len), *tp); 00315 (*out_len)++; 00316 } 00317 sprintf((char *) (*buf + *out_len), "]"); 00318 *out_len += strlen((char *) (*buf + *out_len)); 00319 } 00320 return 1; 00321 } 00322 00323 int 00324 sprint_realloc_hexstring(u_char ** buf, size_t * buf_len, size_t * out_len, 00325 int allow_realloc, const u_char * cp, size_t len) 00326 { 00327 int line_len = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 00328 NETSNMP_DS_LIB_HEX_OUTPUT_LENGTH); 00329 if (!line_len) 00330 line_len=len; 00331 00332 for (; (int)len > line_len; len -= line_len) { 00333 if(!_sprint_hexstring_line(buf, buf_len, out_len, allow_realloc, cp, line_len)) 00334 return 0; 00335 *(*buf + (*out_len)++) = '\n'; 00336 *(*buf + *out_len) = 0; 00337 cp += line_len; 00338 } 00339 if(!_sprint_hexstring_line(buf, buf_len, out_len, allow_realloc, cp, len)) 00340 return 0; 00341 *(*buf + *out_len) = 0; 00342 return 1; 00343 } 00344 00345 00346 00366 int 00367 sprint_realloc_asciistring(u_char ** buf, size_t * buf_len, 00368 size_t * out_len, int allow_realloc, 00369 const u_char * cp, size_t len) 00370 { 00371 int i; 00372 00373 for (i = 0; i < (int) len; i++) { 00374 if (isprint(*cp) || isspace(*cp)) { 00375 if (*cp == '\\' || *cp == '"') { 00376 if ((*out_len >= *buf_len) && 00377 !(allow_realloc && snmp_realloc(buf, buf_len))) { 00378 return 0; 00379 } 00380 *(*buf + (*out_len)++) = '\\'; 00381 } 00382 if ((*out_len >= *buf_len) && 00383 !(allow_realloc && snmp_realloc(buf, buf_len))) { 00384 return 0; 00385 } 00386 *(*buf + (*out_len)++) = *cp++; 00387 } else { 00388 if ((*out_len >= *buf_len) && 00389 !(allow_realloc && snmp_realloc(buf, buf_len))) { 00390 return 0; 00391 } 00392 *(*buf + (*out_len)++) = '.'; 00393 cp++; 00394 } 00395 } 00396 if ((*out_len >= *buf_len) && 00397 !(allow_realloc && snmp_realloc(buf, buf_len))) { 00398 return 0; 00399 } 00400 *(*buf + *out_len) = '\0'; 00401 return 1; 00402 } 00403 00426 int 00427 sprint_realloc_octet_string(u_char ** buf, size_t * buf_len, 00428 size_t * out_len, int allow_realloc, 00429 const netsnmp_variable_list * var, 00430 const struct enum_list *enums, const char *hint, 00431 const char *units) 00432 { 00433 size_t saved_out_len = *out_len; 00434 const char *saved_hint = hint; 00435 int hex = 0, x = 0; 00436 u_char *cp; 00437 int output_format; 00438 00439 if ((var->type != ASN_OCTET_STR) && 00440 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 00441 const char str[] = "Wrong Type (should be OCTET STRING): "; 00442 if (snmp_cstrcat 00443 (buf, buf_len, out_len, allow_realloc, str)) { 00444 return sprint_realloc_by_type(buf, buf_len, out_len, 00445 allow_realloc, var, NULL, NULL, 00446 NULL); 00447 } else { 00448 return 0; 00449 } 00450 } 00451 00452 00453 if (hint) { 00454 int repeat, width = 1; 00455 long value; 00456 char code = 'd', separ = 0, term = 0, ch, intbuf[16]; 00457 u_char *ecp; 00458 00459 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 00460 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "STRING: ")) { 00461 return 0; 00462 } 00463 } 00464 cp = var->val.string; 00465 ecp = cp + var->val_len; 00466 00467 while (cp < ecp) { 00468 repeat = 1; 00469 if (*hint) { 00470 if (*hint == '*') { 00471 repeat = *cp++; 00472 hint++; 00473 } 00474 width = 0; 00475 while ('0' <= *hint && *hint <= '9') 00476 width = (width * 10) + (*hint++ - '0'); 00477 code = *hint++; 00478 if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9') 00479 && (width != 0 00480 || (ch != 'x' && ch != 'd' && ch != 'o'))) 00481 separ = *hint++; 00482 else 00483 separ = 0; 00484 if ((ch = *hint) && ch != '*' && (ch < '0' || ch > '9') 00485 && (width != 0 00486 || (ch != 'x' && ch != 'd' && ch != 'o'))) 00487 term = *hint++; 00488 else 00489 term = 0; 00490 if (width == 0) /* Handle malformed hint strings */ 00491 width = 1; 00492 } 00493 00494 while (repeat && cp < ecp) { 00495 value = 0; 00496 if (code != 'a' && code != 't') { 00497 for (x = 0; x < width; x++) { 00498 value = value * 256 + *cp++; 00499 } 00500 } 00501 switch (code) { 00502 case 'x': 00503 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 00504 NETSNMP_DS_LIB_2DIGIT_HEX_OUTPUT) 00505 && value < 16) { 00506 sprintf(intbuf, "0%lx", value); 00507 } else { 00508 sprintf(intbuf, "%lx", value); 00509 } 00510 if (!snmp_cstrcat 00511 (buf, buf_len, out_len, allow_realloc, intbuf)) { 00512 return 0; 00513 } 00514 break; 00515 case 'd': 00516 sprintf(intbuf, "%ld", value); 00517 if (!snmp_cstrcat 00518 (buf, buf_len, out_len, allow_realloc, intbuf)) { 00519 return 0; 00520 } 00521 break; 00522 case 'o': 00523 sprintf(intbuf, "%lo", value); 00524 if (!snmp_cstrcat 00525 (buf, buf_len, out_len, allow_realloc, intbuf)) { 00526 return 0; 00527 } 00528 break; 00529 case 't': /* new in rfc 3411 */ 00530 case 'a': 00531 while ((*out_len + width + 1) >= *buf_len) { 00532 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 00533 return 0; 00534 } 00535 } 00536 for (x = 0; x < width && cp < ecp; x++) { 00537 *(*buf + *out_len) = *cp++; 00538 (*out_len)++; 00539 } 00540 *(*buf + *out_len) = '\0'; 00541 break; 00542 default: 00543 *out_len = saved_out_len; 00544 if (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 00545 "(Bad hint ignored: ") 00546 && snmp_cstrcat(buf, buf_len, out_len, 00547 allow_realloc, saved_hint) 00548 && snmp_cstrcat(buf, buf_len, out_len, 00549 allow_realloc, ") ")) { 00550 return sprint_realloc_octet_string(buf, buf_len, 00551 out_len, 00552 allow_realloc, 00553 var, enums, 00554 NULL, NULL); 00555 } else { 00556 return 0; 00557 } 00558 } 00559 00560 if (cp < ecp && separ) { 00561 while ((*out_len + 1) >= *buf_len) { 00562 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 00563 return 0; 00564 } 00565 } 00566 *(*buf + *out_len) = separ; 00567 (*out_len)++; 00568 *(*buf + *out_len) = '\0'; 00569 } 00570 repeat--; 00571 } 00572 00573 if (term && cp < ecp) { 00574 while ((*out_len + 1) >= *buf_len) { 00575 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 00576 return 0; 00577 } 00578 } 00579 *(*buf + *out_len) = term; 00580 (*out_len)++; 00581 *(*buf + *out_len) = '\0'; 00582 } 00583 } 00584 00585 if (units) { 00586 return (snmp_cstrcat 00587 (buf, buf_len, out_len, allow_realloc, " ") 00588 && snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units)); 00589 } 00590 if ((*out_len >= *buf_len) && 00591 !(allow_realloc && snmp_realloc(buf, buf_len))) { 00592 return 0; 00593 } 00594 *(*buf + *out_len) = '\0'; 00595 00596 return 1; 00597 } 00598 00599 output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT); 00600 if (0 == output_format) { 00601 output_format = NETSNMP_STRING_OUTPUT_GUESS; 00602 } 00603 switch (output_format) { 00604 case NETSNMP_STRING_OUTPUT_GUESS: 00605 hex = 0; 00606 for (cp = var->val.string, x = 0; x < (int) var->val_len; x++, cp++) { 00607 if (!isprint(*cp) && !isspace(*cp)) { 00608 hex = 1; 00609 } 00610 } 00611 break; 00612 00613 case NETSNMP_STRING_OUTPUT_ASCII: 00614 hex = 0; 00615 break; 00616 00617 case NETSNMP_STRING_OUTPUT_HEX: 00618 hex = 1; 00619 break; 00620 } 00621 00622 if (var->val_len == 0) { 00623 return snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\""); 00624 } 00625 00626 if (hex) { 00627 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 00628 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"")) { 00629 return 0; 00630 } 00631 } else { 00632 if (!snmp_cstrcat 00633 (buf, buf_len, out_len, allow_realloc, "Hex-STRING: ")) { 00634 return 0; 00635 } 00636 } 00637 00638 if (!sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc, 00639 var->val.string, var->val_len)) { 00640 return 0; 00641 } 00642 00643 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 00644 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"")) { 00645 return 0; 00646 } 00647 } 00648 } else { 00649 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 00650 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 00651 "STRING: ")) { 00652 return 0; 00653 } 00654 } 00655 if (!snmp_cstrcat 00656 (buf, buf_len, out_len, allow_realloc, "\"")) { 00657 return 0; 00658 } 00659 if (!sprint_realloc_asciistring 00660 (buf, buf_len, out_len, allow_realloc, var->val.string, 00661 var->val_len)) { 00662 return 0; 00663 } 00664 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"")) { 00665 return 0; 00666 } 00667 } 00668 00669 if (units) { 00670 return (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " ") 00671 && snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units)); 00672 } 00673 return 1; 00674 } 00675 00676 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 00677 00700 int 00701 sprint_realloc_float(u_char ** buf, size_t * buf_len, 00702 size_t * out_len, int allow_realloc, 00703 const netsnmp_variable_list * var, 00704 const struct enum_list *enums, 00705 const char *hint, const char *units) 00706 { 00707 if ((var->type != ASN_OPAQUE_FLOAT) && 00708 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 00709 if (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 00710 "Wrong Type (should be Float): ")) { 00711 return sprint_realloc_by_type(buf, buf_len, out_len, 00712 allow_realloc, var, NULL, NULL, 00713 NULL); 00714 } else { 00715 return 0; 00716 } 00717 } 00718 00719 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 00720 if (!snmp_cstrcat 00721 (buf, buf_len, out_len, allow_realloc, "Opaque: Float: ")) { 00722 return 0; 00723 } 00724 } 00725 00726 00727 /* 00728 * How much space needed for max. length float? 128 is overkill. 00729 */ 00730 00731 while ((*out_len + 128 + 1) >= *buf_len) { 00732 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 00733 return 0; 00734 } 00735 } 00736 00737 sprintf((char *) (*buf + *out_len), "%f", *var->val.floatVal); 00738 *out_len += strlen((char *) (*buf + *out_len)); 00739 00740 if (units) { 00741 return (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " ") 00742 && snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units)); 00743 } 00744 return 1; 00745 } 00746 00747 00770 int 00771 sprint_realloc_double(u_char ** buf, size_t * buf_len, 00772 size_t * out_len, int allow_realloc, 00773 const netsnmp_variable_list * var, 00774 const struct enum_list *enums, 00775 const char *hint, const char *units) 00776 { 00777 if ((var->type != ASN_OPAQUE_DOUBLE) && 00778 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 00779 if (snmp_cstrcat 00780 (buf, buf_len, out_len, allow_realloc, 00781 "Wrong Type (should be Double): ")) { 00782 return sprint_realloc_by_type(buf, buf_len, out_len, 00783 allow_realloc, var, NULL, NULL, 00784 NULL); 00785 } else { 00786 return 0; 00787 } 00788 } 00789 00790 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 00791 if (!snmp_cstrcat 00792 (buf, buf_len, out_len, allow_realloc, "Opaque: Float: ")) { 00793 return 0; 00794 } 00795 } 00796 00797 /* 00798 * How much space needed for max. length double? 128 is overkill. 00799 */ 00800 00801 while ((*out_len + 128 + 1) >= *buf_len) { 00802 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 00803 return 0; 00804 } 00805 } 00806 00807 sprintf((char *) (*buf + *out_len), "%f", *var->val.doubleVal); 00808 *out_len += strlen((char *) (*buf + *out_len)); 00809 00810 if (units) { 00811 return (snmp_cstrcat 00812 (buf, buf_len, out_len, allow_realloc, " ") 00813 && snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units)); 00814 } 00815 return 1; 00816 } 00817 00818 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 00819 00820 00843 int 00844 sprint_realloc_counter64(u_char ** buf, size_t * buf_len, size_t * out_len, 00845 int allow_realloc, 00846 const netsnmp_variable_list * var, 00847 const struct enum_list *enums, 00848 const char *hint, const char *units) 00849 { 00850 char a64buf[I64CHARSZ + 1]; 00851 00852 if ((var->type != ASN_COUNTER64 00853 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 00854 && var->type != ASN_OPAQUE_COUNTER64 00855 && var->type != ASN_OPAQUE_I64 && var->type != ASN_OPAQUE_U64 00856 #endif 00857 ) && (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 00858 if (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 00859 "Wrong Type (should be Counter64): ")) { 00860 return sprint_realloc_by_type(buf, buf_len, out_len, 00861 allow_realloc, var, NULL, NULL, 00862 NULL); 00863 } else { 00864 return 0; 00865 } 00866 } 00867 00868 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 00869 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 00870 if (var->type != ASN_COUNTER64) { 00871 if (!snmp_cstrcat 00872 (buf, buf_len, out_len, allow_realloc, "Opaque: ")) { 00873 return 0; 00874 } 00875 } 00876 #endif 00877 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 00878 switch (var->type) { 00879 case ASN_OPAQUE_U64: 00880 if (!snmp_cstrcat 00881 (buf, buf_len, out_len, allow_realloc, "UInt64: ")) { 00882 return 0; 00883 } 00884 break; 00885 case ASN_OPAQUE_I64: 00886 if (!snmp_cstrcat 00887 (buf, buf_len, out_len, allow_realloc, "Int64: ")) { 00888 return 0; 00889 } 00890 break; 00891 case ASN_COUNTER64: 00892 case ASN_OPAQUE_COUNTER64: 00893 #endif 00894 if (!snmp_cstrcat 00895 (buf, buf_len, out_len, allow_realloc, "Counter64: ")) { 00896 return 0; 00897 } 00898 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 00899 } 00900 #endif 00901 } 00902 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 00903 if (var->type == ASN_OPAQUE_I64) { 00904 printI64(a64buf, var->val.counter64); 00905 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, a64buf)) { 00906 return 0; 00907 } 00908 } else { 00909 #endif 00910 printU64(a64buf, var->val.counter64); 00911 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, a64buf)) { 00912 return 0; 00913 } 00914 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 00915 } 00916 #endif 00917 00918 if (units) { 00919 return (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " ") 00920 && snmp_cstrcat(buf, buf_len, out_len, allow_realloc, units)); 00921 } 00922 return 1; 00923 } 00924 00925 00946 int 00947 sprint_realloc_opaque(u_char ** buf, size_t * buf_len, 00948 size_t * out_len, int allow_realloc, 00949 const netsnmp_variable_list * var, 00950 const struct enum_list *enums, 00951 const char *hint, const char *units) 00952 { 00953 if ((var->type != ASN_OPAQUE 00954 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 00955 && var->type != ASN_OPAQUE_COUNTER64 00956 && var->type != ASN_OPAQUE_U64 00957 && var->type != ASN_OPAQUE_I64 00958 && var->type != ASN_OPAQUE_FLOAT && var->type != ASN_OPAQUE_DOUBLE 00959 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 00960 ) && (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 00961 if (snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 00962 "Wrong Type (should be Opaque): ")) { 00963 return sprint_realloc_by_type(buf, buf_len, out_len, 00964 allow_realloc, var, NULL, NULL, 00965 NULL); 00966 } else { 00967 return 0; 00968 } 00969 } 00970 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 00971 switch (var->type) { 00972 case ASN_OPAQUE_COUNTER64: 00973 case ASN_OPAQUE_U64: 00974 case ASN_OPAQUE_I64: 00975 return sprint_realloc_counter64(buf, buf_len, out_len, 00976 allow_realloc, var, enums, hint, 00977 units); 00978 break; 00979 00980 case ASN_OPAQUE_FLOAT: 00981 return sprint_realloc_float(buf, buf_len, out_len, allow_realloc, 00982 var, enums, hint, units); 00983 break; 00984 00985 case ASN_OPAQUE_DOUBLE: 00986 return sprint_realloc_double(buf, buf_len, out_len, allow_realloc, 00987 var, enums, hint, units); 00988 break; 00989 00990 case ASN_OPAQUE: 00991 #endif 00992 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 00993 u_char str[] = "OPAQUE: "; 00994 if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 00995 return 0; 00996 } 00997 } 00998 if (!sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc, 00999 var->val.string, var->val_len)) { 01000 return 0; 01001 } 01002 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 01003 } 01004 #endif 01005 if (units) { 01006 return (snmp_strcat 01007 (buf, buf_len, out_len, allow_realloc, 01008 (const u_char *) " ") 01009 && snmp_strcat(buf, buf_len, out_len, allow_realloc, 01010 (const u_char *) units)); 01011 } 01012 return 1; 01013 } 01014 01015 01036 int 01037 sprint_realloc_object_identifier(u_char ** buf, size_t * buf_len, 01038 size_t * out_len, int allow_realloc, 01039 const netsnmp_variable_list * var, 01040 const struct enum_list *enums, 01041 const char *hint, const char *units) 01042 { 01043 int buf_overflow = 0; 01044 01045 if ((var->type != ASN_OBJECT_ID) && 01046 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 01047 u_char str[] = 01048 "Wrong Type (should be OBJECT IDENTIFIER): "; 01049 if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01050 return sprint_realloc_by_type(buf, buf_len, out_len, 01051 allow_realloc, var, NULL, NULL, 01052 NULL); 01053 } else { 01054 return 0; 01055 } 01056 } 01057 01058 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01059 u_char str[] = "OID: "; 01060 if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01061 return 0; 01062 } 01063 } 01064 01065 netsnmp_sprint_realloc_objid_tree(buf, buf_len, out_len, allow_realloc, 01066 &buf_overflow, 01067 (oid *) (var->val.objid), 01068 var->val_len / sizeof(oid)); 01069 01070 if (buf_overflow) { 01071 return 0; 01072 } 01073 01074 if (units) { 01075 return (snmp_strcat 01076 (buf, buf_len, out_len, allow_realloc, 01077 (const u_char *) " ") 01078 && snmp_strcat(buf, buf_len, out_len, allow_realloc, 01079 (const u_char *) units)); 01080 } 01081 return 1; 01082 } 01083 01084 01085 01106 int 01107 sprint_realloc_timeticks(u_char ** buf, size_t * buf_len, size_t * out_len, 01108 int allow_realloc, 01109 const netsnmp_variable_list * var, 01110 const struct enum_list *enums, 01111 const char *hint, const char *units) 01112 { 01113 char timebuf[40]; 01114 01115 if ((var->type != ASN_TIMETICKS) && 01116 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 01117 u_char str[] = "Wrong Type (should be Timeticks): "; 01118 if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01119 return sprint_realloc_by_type(buf, buf_len, out_len, 01120 allow_realloc, var, NULL, NULL, 01121 NULL); 01122 } else { 01123 return 0; 01124 } 01125 } 01126 01127 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS)) { 01128 char str[16]; 01129 sprintf(str, "%lu", *(u_long *) var->val.integer); 01130 if (!snmp_strcat 01131 (buf, buf_len, out_len, allow_realloc, (const u_char *) str)) { 01132 return 0; 01133 } 01134 return 1; 01135 } 01136 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01137 char str[32]; 01138 sprintf(str, "Timeticks: (%lu) ", *(u_long *) var->val.integer); 01139 if (!snmp_strcat 01140 (buf, buf_len, out_len, allow_realloc, (const u_char *) str)) { 01141 return 0; 01142 } 01143 } 01144 uptimeString(*(u_long *) (var->val.integer), timebuf, sizeof(timebuf)); 01145 if (!snmp_strcat 01146 (buf, buf_len, out_len, allow_realloc, (const u_char *) timebuf)) { 01147 return 0; 01148 } 01149 if (units) { 01150 return (snmp_strcat 01151 (buf, buf_len, out_len, allow_realloc, 01152 (const u_char *) " ") 01153 && snmp_strcat(buf, buf_len, out_len, allow_realloc, 01154 (const u_char *) units)); 01155 } 01156 return 1; 01157 } 01158 01159 01180 int 01181 sprint_realloc_hinted_integer(u_char ** buf, size_t * buf_len, 01182 size_t * out_len, int allow_realloc, 01183 long val, const char decimaltype, 01184 const char *hint, const char *units) 01185 { 01186 char fmt[10] = "%l@", tmp[256]; 01187 int shift, len; 01188 01189 if (hint[1] == '-') { 01190 shift = atoi(hint + 2); 01191 } else { 01192 shift = 0; 01193 } 01194 01195 if (hint[0] == 'd') { 01196 /* 01197 * We might *actually* want a 'u' here. 01198 */ 01199 fmt[2] = decimaltype; 01200 } else { 01201 /* 01202 * DISPLAY-HINT character is 'b', 'o', or 'x'. 01203 */ 01204 fmt[2] = hint[0]; 01205 } 01206 01207 sprintf(tmp, fmt, val); 01208 if (shift != 0) { 01209 len = strlen(tmp); 01210 if (shift <= len) { 01211 tmp[len + 1] = 0; 01212 while (shift--) { 01213 tmp[len] = tmp[len - 1]; 01214 len--; 01215 } 01216 tmp[len] = '.'; 01217 } else { 01218 tmp[shift + 1] = 0; 01219 while (shift) { 01220 if (len-- > 0) { 01221 tmp[shift] = tmp[len]; 01222 } else { 01223 tmp[shift] = '0'; 01224 } 01225 shift--; 01226 } 01227 tmp[0] = '.'; 01228 } 01229 } 01230 return snmp_strcat(buf, buf_len, out_len, allow_realloc, (u_char *)tmp); 01231 } 01232 01233 01254 int 01255 sprint_realloc_integer(u_char ** buf, size_t * buf_len, size_t * out_len, 01256 int allow_realloc, 01257 const netsnmp_variable_list * var, 01258 const struct enum_list *enums, 01259 const char *hint, const char *units) 01260 { 01261 char *enum_string = NULL; 01262 01263 if ((var->type != ASN_INTEGER) && 01264 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 01265 u_char str[] = "Wrong Type (should be INTEGER): "; 01266 if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01267 return sprint_realloc_by_type(buf, buf_len, out_len, 01268 allow_realloc, var, NULL, NULL, 01269 NULL); 01270 } else { 01271 return 0; 01272 } 01273 } 01274 for (; enums; enums = enums->next) { 01275 if (enums->value == *var->val.integer) { 01276 enum_string = enums->label; 01277 break; 01278 } 01279 } 01280 01281 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01282 if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, 01283 (const u_char *) "INTEGER: ")) { 01284 return 0; 01285 } 01286 } 01287 01288 if (enum_string == NULL || 01289 netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) { 01290 if (hint) { 01291 if (!(sprint_realloc_hinted_integer(buf, buf_len, out_len, 01292 allow_realloc, 01293 *var->val.integer, 'd', 01294 hint, units))) { 01295 return 0; 01296 } 01297 } else { 01298 char str[16]; 01299 sprintf(str, "%ld", *var->val.integer); 01300 if (!snmp_strcat 01301 (buf, buf_len, out_len, allow_realloc, 01302 (const u_char *) str)) { 01303 return 0; 01304 } 01305 } 01306 } else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01307 if (!snmp_strcat 01308 (buf, buf_len, out_len, allow_realloc, 01309 (const u_char *) enum_string)) { 01310 return 0; 01311 } 01312 } else { 01313 char str[16]; 01314 sprintf(str, "(%ld)", *var->val.integer); 01315 if (!snmp_strcat 01316 (buf, buf_len, out_len, allow_realloc, 01317 (const u_char *) enum_string)) { 01318 return 0; 01319 } 01320 if (!snmp_strcat 01321 (buf, buf_len, out_len, allow_realloc, (const u_char *) str)) { 01322 return 0; 01323 } 01324 } 01325 01326 if (units) { 01327 return (snmp_strcat 01328 (buf, buf_len, out_len, allow_realloc, 01329 (const u_char *) " ") 01330 && snmp_strcat(buf, buf_len, out_len, allow_realloc, 01331 (const u_char *) units)); 01332 } 01333 return 1; 01334 } 01335 01336 01357 int 01358 sprint_realloc_uinteger(u_char ** buf, size_t * buf_len, size_t * out_len, 01359 int allow_realloc, 01360 const netsnmp_variable_list * var, 01361 const struct enum_list *enums, 01362 const char *hint, const char *units) 01363 { 01364 char *enum_string = NULL; 01365 01366 if ((var->type != ASN_UINTEGER) && 01367 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 01368 u_char str[] = "Wrong Type (should be UInteger32): "; 01369 if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01370 return sprint_realloc_by_type(buf, buf_len, out_len, 01371 allow_realloc, var, NULL, NULL, 01372 NULL); 01373 } else { 01374 return 0; 01375 } 01376 } 01377 01378 for (; enums; enums = enums->next) { 01379 if (enums->value == *var->val.integer) { 01380 enum_string = enums->label; 01381 break; 01382 } 01383 } 01384 01385 if (enum_string == NULL || 01386 netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) { 01387 if (hint) { 01388 if (!(sprint_realloc_hinted_integer(buf, buf_len, out_len, 01389 allow_realloc, 01390 *var->val.integer, 'u', 01391 hint, units))) { 01392 return 0; 01393 } 01394 } else { 01395 char str[16]; 01396 sprintf(str, "%lu", *var->val.integer); 01397 if (!snmp_strcat 01398 (buf, buf_len, out_len, allow_realloc, 01399 (const u_char *) str)) { 01400 return 0; 01401 } 01402 } 01403 } else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01404 if (!snmp_strcat 01405 (buf, buf_len, out_len, allow_realloc, 01406 (const u_char *) enum_string)) { 01407 return 0; 01408 } 01409 } else { 01410 char str[16]; 01411 sprintf(str, "(%lu)", *var->val.integer); 01412 if (!snmp_strcat 01413 (buf, buf_len, out_len, allow_realloc, 01414 (const u_char *) enum_string)) { 01415 return 0; 01416 } 01417 if (!snmp_strcat 01418 (buf, buf_len, out_len, allow_realloc, (const u_char *) str)) { 01419 return 0; 01420 } 01421 } 01422 01423 if (units) { 01424 return (snmp_strcat 01425 (buf, buf_len, out_len, allow_realloc, 01426 (const u_char *) " ") 01427 && snmp_strcat(buf, buf_len, out_len, allow_realloc, 01428 (const u_char *) units)); 01429 } 01430 return 1; 01431 } 01432 01433 01454 int 01455 sprint_realloc_gauge(u_char ** buf, size_t * buf_len, size_t * out_len, 01456 int allow_realloc, 01457 const netsnmp_variable_list * var, 01458 const struct enum_list *enums, 01459 const char *hint, const char *units) 01460 { 01461 char tmp[32]; 01462 01463 if ((var->type != ASN_GAUGE) && 01464 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 01465 u_char str[] = 01466 "Wrong Type (should be Gauge32 or Unsigned32): "; 01467 if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01468 return sprint_realloc_by_type(buf, buf_len, out_len, 01469 allow_realloc, var, NULL, NULL, 01470 NULL); 01471 } else { 01472 return 0; 01473 } 01474 } 01475 01476 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01477 u_char str[] = "Gauge32: "; 01478 if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01479 return 0; 01480 } 01481 } 01482 if (hint) { 01483 if (!sprint_realloc_hinted_integer(buf, buf_len, out_len, 01484 allow_realloc, 01485 *var->val.integer, 'u', hint, 01486 units)) { 01487 return 0; 01488 } 01489 } else { 01490 sprintf(tmp, "%lu", *var->val.integer); 01491 if (!snmp_strcat 01492 (buf, buf_len, out_len, allow_realloc, (const u_char *) tmp)) { 01493 return 0; 01494 } 01495 } 01496 if (units) { 01497 return (snmp_strcat 01498 (buf, buf_len, out_len, allow_realloc, 01499 (const u_char *) " ") 01500 && snmp_strcat(buf, buf_len, out_len, allow_realloc, 01501 (const u_char *) units)); 01502 } 01503 return 1; 01504 } 01505 01506 01527 int 01528 sprint_realloc_counter(u_char ** buf, size_t * buf_len, size_t * out_len, 01529 int allow_realloc, 01530 const netsnmp_variable_list * var, 01531 const struct enum_list *enums, 01532 const char *hint, const char *units) 01533 { 01534 char tmp[32]; 01535 01536 if ((var->type != ASN_COUNTER) && 01537 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 01538 u_char str[] = "Wrong Type (should be Counter32): "; 01539 if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01540 return sprint_realloc_by_type(buf, buf_len, out_len, 01541 allow_realloc, var, NULL, NULL, 01542 NULL); 01543 } else { 01544 return 0; 01545 } 01546 } 01547 01548 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01549 u_char str[] = "Counter32: "; 01550 if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01551 return 0; 01552 } 01553 } 01554 sprintf(tmp, "%lu", *var->val.integer); 01555 if (!snmp_strcat 01556 (buf, buf_len, out_len, allow_realloc, (const u_char *) tmp)) { 01557 return 0; 01558 } 01559 if (units) { 01560 return (snmp_strcat 01561 (buf, buf_len, out_len, allow_realloc, 01562 (const u_char *) " ") 01563 && snmp_strcat(buf, buf_len, out_len, allow_realloc, 01564 (const u_char *) units)); 01565 } 01566 return 1; 01567 } 01568 01569 01590 int 01591 sprint_realloc_networkaddress(u_char ** buf, size_t * buf_len, 01592 size_t * out_len, int allow_realloc, 01593 const netsnmp_variable_list * var, 01594 const struct enum_list *enums, const char *hint, 01595 const char *units) 01596 { 01597 size_t i; 01598 01599 if ((var->type != ASN_IPADDRESS) && 01600 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 01601 u_char str[] = "Wrong Type (should be NetworkAddress): "; 01602 if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01603 return sprint_realloc_by_type(buf, buf_len, out_len, 01604 allow_realloc, var, NULL, NULL, 01605 NULL); 01606 } else { 01607 return 0; 01608 } 01609 } 01610 01611 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01612 u_char str[] = "Network Address: "; 01613 if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01614 return 0; 01615 } 01616 } 01617 01618 while ((*out_len + (var->val_len * 3) + 2) >= *buf_len) { 01619 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 01620 return 0; 01621 } 01622 } 01623 01624 for (i = 0; i < var->val_len; i++) { 01625 sprintf((char *) (*buf + *out_len), "%02X", var->val.string[i]); 01626 *out_len += 2; 01627 if (i < var->val_len - 1) { 01628 *(*buf + *out_len) = ':'; 01629 (*out_len)++; 01630 } 01631 } 01632 return 1; 01633 } 01634 01635 01656 int 01657 sprint_realloc_ipaddress(u_char ** buf, size_t * buf_len, size_t * out_len, 01658 int allow_realloc, 01659 const netsnmp_variable_list * var, 01660 const struct enum_list *enums, 01661 const char *hint, const char *units) 01662 { 01663 u_char *ip = var->val.string; 01664 01665 if ((var->type != ASN_IPADDRESS) && 01666 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 01667 u_char str[] = "Wrong Type (should be IpAddress): "; 01668 if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01669 return sprint_realloc_by_type(buf, buf_len, out_len, 01670 allow_realloc, var, NULL, NULL, 01671 NULL); 01672 } else { 01673 return 0; 01674 } 01675 } 01676 01677 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01678 u_char str[] = "IpAddress: "; 01679 if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01680 return 0; 01681 } 01682 } 01683 while ((*out_len + 17) >= *buf_len) { 01684 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 01685 return 0; 01686 } 01687 } 01688 if (ip) 01689 sprintf((char *) (*buf + *out_len), "%d.%d.%d.%d", 01690 ip[0], ip[1], ip[2], ip[3]); 01691 *out_len += strlen((char *) (*buf + *out_len)); 01692 return 1; 01693 } 01694 01695 01716 int 01717 sprint_realloc_null(u_char ** buf, size_t * buf_len, size_t * out_len, 01718 int allow_realloc, 01719 const netsnmp_variable_list * var, 01720 const struct enum_list *enums, 01721 const char *hint, const char *units) 01722 { 01723 if ((var->type != ASN_NULL) && 01724 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 01725 u_char str[] = "Wrong Type (should be NULL): "; 01726 if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01727 return sprint_realloc_by_type(buf, buf_len, out_len, 01728 allow_realloc, var, NULL, NULL, 01729 NULL); 01730 } else { 01731 return 0; 01732 } 01733 } else { 01734 u_char str[] = "NULL"; 01735 return snmp_strcat(buf, buf_len, out_len, allow_realloc, str); 01736 } 01737 } 01738 01739 01760 int 01761 sprint_realloc_bitstring(u_char ** buf, size_t * buf_len, size_t * out_len, 01762 int allow_realloc, 01763 const netsnmp_variable_list * var, 01764 const struct enum_list *enums, 01765 const char *hint, const char *units) 01766 { 01767 int len, bit; 01768 u_char *cp; 01769 char *enum_string; 01770 01771 if ((var->type != ASN_BIT_STR && var->type != ASN_OCTET_STR) && 01772 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 01773 u_char str[] = "Wrong Type (should be BITS): "; 01774 if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01775 return sprint_realloc_by_type(buf, buf_len, out_len, 01776 allow_realloc, var, NULL, NULL, 01777 NULL); 01778 } else { 01779 return 0; 01780 } 01781 } 01782 01783 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01784 u_char str[] = "\""; 01785 if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01786 return 0; 01787 } 01788 } else { 01789 u_char str[] = "BITS: "; 01790 if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01791 return 0; 01792 } 01793 } 01794 if (!sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc, 01795 var->val.bitstring, var->val_len)) { 01796 return 0; 01797 } 01798 01799 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01800 u_char str[] = "\""; 01801 if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01802 return 0; 01803 } 01804 } else { 01805 cp = var->val.bitstring; 01806 for (len = 0; len < (int) var->val_len; len++) { 01807 for (bit = 0; bit < 8; bit++) { 01808 if (*cp & (0x80 >> bit)) { 01809 enum_string = NULL; 01810 for (; enums; enums = enums->next) { 01811 if (enums->value == (len * 8) + bit) { 01812 enum_string = enums->label; 01813 break; 01814 } 01815 } 01816 if (enum_string == NULL || 01817 netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 01818 NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM)) { 01819 char str[16]; 01820 sprintf(str, "%d ", (len * 8) + bit); 01821 if (!snmp_strcat 01822 (buf, buf_len, out_len, allow_realloc, 01823 (const u_char *) str)) { 01824 return 0; 01825 } 01826 } else { 01827 char str[16]; 01828 sprintf(str, "(%d) ", (len * 8) + bit); 01829 if (!snmp_strcat 01830 (buf, buf_len, out_len, allow_realloc, 01831 (const u_char *) enum_string)) { 01832 return 0; 01833 } 01834 if (!snmp_strcat 01835 (buf, buf_len, out_len, allow_realloc, 01836 (const u_char *) str)) { 01837 return 0; 01838 } 01839 } 01840 } 01841 } 01842 cp++; 01843 } 01844 } 01845 return 1; 01846 } 01847 01848 int 01849 sprint_realloc_nsapaddress(u_char ** buf, size_t * buf_len, 01850 size_t * out_len, int allow_realloc, 01851 const netsnmp_variable_list * var, 01852 const struct enum_list *enums, const char *hint, 01853 const char *units) 01854 { 01855 if ((var->type != ASN_NSAP) && 01856 (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT))) { 01857 u_char str[] = "Wrong Type (should be NsapAddress): "; 01858 if (snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01859 return sprint_realloc_by_type(buf, buf_len, out_len, 01860 allow_realloc, var, NULL, NULL, 01861 NULL); 01862 } else { 01863 return 0; 01864 } 01865 } 01866 01867 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 01868 u_char str[] = "NsapAddress: "; 01869 if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, str)) { 01870 return 0; 01871 } 01872 } 01873 01874 return sprint_realloc_hexstring(buf, buf_len, out_len, allow_realloc, 01875 var->val.string, var->val_len); 01876 } 01877 01878 01899 int 01900 sprint_realloc_badtype(u_char ** buf, size_t * buf_len, size_t * out_len, 01901 int allow_realloc, 01902 const netsnmp_variable_list * var, 01903 const struct enum_list *enums, 01904 const char *hint, const char *units) 01905 { 01906 u_char str[] = "Variable has bad type"; 01907 01908 return snmp_strcat(buf, buf_len, out_len, allow_realloc, str); 01909 } 01910 01911 01912 01934 int 01935 sprint_realloc_by_type(u_char ** buf, size_t * buf_len, size_t * out_len, 01936 int allow_realloc, 01937 const netsnmp_variable_list * var, 01938 const struct enum_list *enums, 01939 const char *hint, const char *units) 01940 { 01941 DEBUGMSGTL(("output", "sprint_by_type, type %d\n", var->type)); 01942 01943 switch (var->type) { 01944 case ASN_INTEGER: 01945 return sprint_realloc_integer(buf, buf_len, out_len, allow_realloc, 01946 var, enums, hint, units); 01947 case ASN_OCTET_STR: 01948 return sprint_realloc_octet_string(buf, buf_len, out_len, 01949 allow_realloc, var, enums, hint, 01950 units); 01951 case ASN_BIT_STR: 01952 return sprint_realloc_bitstring(buf, buf_len, out_len, 01953 allow_realloc, var, enums, hint, 01954 units); 01955 case ASN_OPAQUE: 01956 return sprint_realloc_opaque(buf, buf_len, out_len, allow_realloc, 01957 var, enums, hint, units); 01958 case ASN_OBJECT_ID: 01959 return sprint_realloc_object_identifier(buf, buf_len, out_len, 01960 allow_realloc, var, enums, 01961 hint, units); 01962 case ASN_TIMETICKS: 01963 return sprint_realloc_timeticks(buf, buf_len, out_len, 01964 allow_realloc, var, enums, hint, 01965 units); 01966 case ASN_GAUGE: 01967 return sprint_realloc_gauge(buf, buf_len, out_len, allow_realloc, 01968 var, enums, hint, units); 01969 case ASN_COUNTER: 01970 return sprint_realloc_counter(buf, buf_len, out_len, allow_realloc, 01971 var, enums, hint, units); 01972 case ASN_IPADDRESS: 01973 return sprint_realloc_ipaddress(buf, buf_len, out_len, 01974 allow_realloc, var, enums, hint, 01975 units); 01976 case ASN_NULL: 01977 return sprint_realloc_null(buf, buf_len, out_len, allow_realloc, 01978 var, enums, hint, units); 01979 case ASN_UINTEGER: 01980 return sprint_realloc_uinteger(buf, buf_len, out_len, 01981 allow_realloc, var, enums, hint, 01982 units); 01983 case ASN_COUNTER64: 01984 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 01985 case ASN_OPAQUE_U64: 01986 case ASN_OPAQUE_I64: 01987 case ASN_OPAQUE_COUNTER64: 01988 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 01989 return sprint_realloc_counter64(buf, buf_len, out_len, 01990 allow_realloc, var, enums, hint, 01991 units); 01992 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 01993 case ASN_OPAQUE_FLOAT: 01994 return sprint_realloc_float(buf, buf_len, out_len, allow_realloc, 01995 var, enums, hint, units); 01996 case ASN_OPAQUE_DOUBLE: 01997 return sprint_realloc_double(buf, buf_len, out_len, allow_realloc, 01998 var, enums, hint, units); 01999 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 02000 default: 02001 DEBUGMSGTL(("sprint_by_type", "bad type: %d\n", var->type)); 02002 return sprint_realloc_badtype(buf, buf_len, out_len, allow_realloc, 02003 var, enums, hint, units); 02004 } 02005 } 02006 02007 02008 #ifndef NETSNMP_DISABLE_MIB_LOADING 02009 02014 struct tree * 02015 get_tree_head(void) 02016 { 02017 return (tree_head); 02018 } 02019 02020 static char *confmibdir = NULL; 02021 static char *confmibs = NULL; 02022 02023 static void 02024 handle_mibdirs_conf(const char *token, char *line) 02025 { 02026 char *ctmp; 02027 02028 if (confmibdir) { 02029 if ((*line == '+') || (*line == '-')) { 02030 ctmp = (char *) malloc(strlen(confmibdir) + strlen(line) + 2); 02031 if (!ctmp) { 02032 DEBUGMSGTL(("read_config:initmib", 02033 "mibdir conf malloc failed")); 02034 return; 02035 } 02036 if(*line++ == '+') 02037 sprintf(ctmp, "%s%c%s", confmibdir, ENV_SEPARATOR_CHAR, line); 02038 else 02039 sprintf(ctmp, "%s%c%s", line, ENV_SEPARATOR_CHAR, confmibdir); 02040 } else { 02041 ctmp = strdup(line); 02042 if (!ctmp) { 02043 DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed")); 02044 return; 02045 } 02046 } 02047 SNMP_FREE(confmibdir); 02048 } else { 02049 ctmp = strdup(line); 02050 if (!ctmp) { 02051 DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed")); 02052 return; 02053 } 02054 } 02055 confmibdir = ctmp; 02056 DEBUGMSGTL(("read_config:initmib", "using mibdirs: %s\n", confmibdir)); 02057 } 02058 02059 static void 02060 handle_mibs_conf(const char *token, char *line) 02061 { 02062 char *ctmp; 02063 02064 if (confmibs) { 02065 if ((*line == '+') || (*line == '-')) { 02066 ctmp = (char *) malloc(strlen(confmibs) + strlen(line) + 2); 02067 if (!ctmp) { 02068 DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed")); 02069 return; 02070 } 02071 if(*line++ == '+') 02072 sprintf(ctmp, "%s%c%s", confmibs, ENV_SEPARATOR_CHAR, line); 02073 else 02074 sprintf(ctmp, "%s%c%s", line, ENV_SEPARATOR_CHAR, confmibdir); 02075 } else { 02076 ctmp = strdup(line); 02077 if (!ctmp) { 02078 DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed")); 02079 return; 02080 } 02081 } 02082 SNMP_FREE(confmibs); 02083 } else { 02084 ctmp = strdup(line); 02085 if (!ctmp) { 02086 DEBUGMSGTL(("read_config:initmib", "mibs conf malloc failed")); 02087 return; 02088 } 02089 } 02090 confmibs = ctmp; 02091 DEBUGMSGTL(("read_config:initmib", "using mibs: %s\n", confmibs)); 02092 } 02093 02094 02095 static void 02096 handle_mibfile_conf(const char *token, char *line) 02097 { 02098 DEBUGMSGTL(("read_config:initmib", "reading mibfile: %s\n", line)); 02099 read_mib(line); 02100 } 02101 #endif 02102 02103 static void 02104 handle_print_numeric(const char *token, char *line) 02105 { 02106 const char *value; 02107 char *st; 02108 02109 value = strtok_r(line, " \t\n", &st); 02110 if ((strcasecmp(value, "yes") == 0) || 02111 (strcasecmp(value, "true") == 0) || 02112 (*value == '1')) { 02113 02114 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 02115 NETSNMP_OID_OUTPUT_NUMERIC); 02116 } 02117 } 02118 02119 char * 02120 snmp_out_toggle_options(char *options) 02121 { 02122 while (*options) { 02123 switch (*options++) { 02124 case '0': 02125 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, 02126 NETSNMP_DS_LIB_2DIGIT_HEX_OUTPUT); 02127 break; 02128 case 'a': 02129 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT, 02130 NETSNMP_STRING_OUTPUT_ASCII); 02131 break; 02132 case 'b': 02133 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS); 02134 break; 02135 case 'e': 02136 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM); 02137 break; 02138 case 'E': 02139 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES); 02140 break; 02141 case 'f': 02142 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 02143 NETSNMP_OID_OUTPUT_FULL); 02144 break; 02145 case 'n': 02146 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 02147 NETSNMP_OID_OUTPUT_NUMERIC); 02148 break; 02149 case 'q': 02150 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT); 02151 break; 02152 case 'Q': 02153 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT, 1); 02154 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT); 02155 break; 02156 case 's': 02157 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 02158 NETSNMP_OID_OUTPUT_SUFFIX); 02159 break; 02160 case 'S': 02161 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 02162 NETSNMP_OID_OUTPUT_MODULE); 02163 break; 02164 case 't': 02165 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS); 02166 break; 02167 case 'T': 02168 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT); 02169 break; 02170 case 'u': 02171 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 02172 NETSNMP_OID_OUTPUT_UCD); 02173 break; 02174 case 'U': 02175 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS); 02176 break; 02177 case 'v': 02178 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE); 02179 break; 02180 case 'x': 02181 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_STRING_OUTPUT_FORMAT, 02182 NETSNMP_STRING_OUTPUT_HEX); 02183 break; 02184 case 'X': 02185 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX); 02186 break; 02187 default: 02188 return options - 1; 02189 } 02190 } 02191 return NULL; 02192 } 02193 02194 void 02195 snmp_out_toggle_options_usage(const char *lead, FILE * outf) 02196 { 02197 fprintf(outf, "%s0: print leading 0 for single-digit hex characters\n", lead); 02198 fprintf(outf, "%sa: print all strings in ascii format\n", lead); 02199 fprintf(outf, "%sb: do not break OID indexes down\n", lead); 02200 fprintf(outf, "%se: print enums numerically\n", lead); 02201 fprintf(outf, "%sE: escape quotes in string indices\n", lead); 02202 fprintf(outf, "%sf: print full OIDs on output\n", lead); 02203 fprintf(outf, "%sn: print OIDs numerically\n", lead); 02204 fprintf(outf, "%sq: quick print for easier parsing\n", lead); 02205 fprintf(outf, "%sQ: quick print with equal-signs\n", lead); /* @@JDW */ 02206 fprintf(outf, "%ss: print only last symbolic element of OID\n", lead); 02207 fprintf(outf, "%sS: print MIB module-id plus last element\n", lead); 02208 fprintf(outf, "%st: print timeticks unparsed as numeric integers\n", 02209 lead); 02210 fprintf(outf, 02211 "%sT: print human-readable text along with hex strings\n", 02212 lead); 02213 fprintf(outf, "%su: print OIDs using UCD-style prefix suppression\n", 02214 lead); 02215 fprintf(outf, "%sU: don't print units\n", lead); 02216 fprintf(outf, "%sv: print values only (not OID = value)\n", lead); 02217 fprintf(outf, "%sx: print all strings in hex format\n", lead); 02218 fprintf(outf, "%sX: extended index format\n", lead); 02219 } 02220 02221 char * 02222 snmp_in_options(char *optarg, int argc, char *const *argv) 02223 { 02224 char *cp; 02225 02226 for (cp = optarg; *cp; cp++) { 02227 switch (*cp) { 02228 case 'b': 02229 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REGEX_ACCESS); 02230 break; 02231 case 'R': 02232 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_RANDOM_ACCESS); 02233 break; 02234 case 'r': 02235 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE); 02236 break; 02237 case 'h': 02238 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_DISPLAY_HINT); 02239 break; 02240 case 'u': 02241 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_READ_UCD_STYLE_OID); 02242 break; 02243 case 's': 02244 /* What if argc/argv are null ? */ 02245 if (!*(++cp)) 02246 cp = argv[optind++]; 02247 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, 02248 NETSNMP_DS_LIB_OIDSUFFIX, 02249 cp); 02250 return NULL; 02251 02252 case 'S': 02253 /* What if argc/argv are null ? */ 02254 if (!*(++cp)) 02255 cp = argv[optind++]; 02256 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, 02257 NETSNMP_DS_LIB_OIDPREFIX, 02258 cp); 02259 return NULL; 02260 02261 default: 02262 /* 02263 * Here? Or in snmp_parse_args? 02264 snmp_log(LOG_ERR, "Unknown input option passed to -I: %c.\n", *cp); 02265 */ 02266 return cp; 02267 } 02268 } 02269 return NULL; 02270 } 02271 02272 char * 02273 snmp_in_toggle_options(char *options) 02274 { 02275 return snmp_in_options( options, 0, NULL ); 02276 } 02277 02278 02286 void 02287 snmp_in_toggle_options_usage(const char *lead, FILE * outf) 02288 { 02289 fprintf(outf, "%sb: do best/regex matching to find a MIB node\n", lead); 02290 fprintf(outf, "%sh: don't apply DISPLAY-HINTs\n", lead); 02291 fprintf(outf, "%sr: do not check values for range/type legality\n", lead); 02292 fprintf(outf, "%sR: do random access to OID labels\n", lead); 02293 fprintf(outf, 02294 "%su: top-level OIDs must have '.' prefix (UCD-style)\n", lead); 02295 fprintf(outf, 02296 "%ss SUFFIX: Append all textual OIDs with SUFFIX before parsing\n", 02297 lead); 02298 fprintf(outf, 02299 "%sS PREFIX: Prepend all textual OIDs with PREFIX before parsing\n", 02300 lead); 02301 } 02302 02303 /*** 02304 * 02305 */ 02306 void 02307 register_mib_handlers(void) 02308 { 02309 #ifndef NETSNMP_DISABLE_MIB_LOADING 02310 register_prenetsnmp_mib_handler("snmp", "mibdirs", 02311 handle_mibdirs_conf, NULL, 02312 "[mib-dirs|+mib-dirs|-mib-dirs]"); 02313 register_prenetsnmp_mib_handler("snmp", "mibs", 02314 handle_mibs_conf, NULL, 02315 "[mib-tokens|+mib-tokens]"); 02316 register_config_handler("snmp", "mibfile", 02317 handle_mibfile_conf, NULL, "mibfile-to-read"); 02318 /* 02319 * register the snmp.conf configuration handlers for default 02320 * parsing behaviour 02321 */ 02322 02323 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "showMibErrors", 02324 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_ERRORS); 02325 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "strictCommentTerm", 02326 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_COMMENT_TERM); 02327 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "mibAllowUnderline", 02328 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_PARSE_LABEL); 02329 netsnmp_ds_register_premib(ASN_INTEGER, "snmp", "mibWarningLevel", 02330 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_WARNINGS); 02331 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "mibReplaceWithLatest", 02332 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_REPLACE); 02333 #endif 02334 02335 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "printNumericEnums", 02336 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM); 02337 register_prenetsnmp_mib_handler("snmp", "printNumericOids", 02338 handle_print_numeric, NULL, "(1|yes|true|0|no|false)"); 02339 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "escapeQuotes", 02340 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES); 02341 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "dontBreakdownOids", 02342 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS); 02343 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "quickPrinting", 02344 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT); 02345 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "numericTimeticks", 02346 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS); 02347 netsnmp_ds_register_premib(ASN_INTEGER, "snmp", "oidOutputFormat", 02348 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT); 02349 netsnmp_ds_register_premib(ASN_INTEGER, "snmp", "suffixPrinting", 02350 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT); 02351 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "extendedIndex", 02352 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX); 02353 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "printHexText", 02354 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_HEX_TEXT); 02355 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "printValueOnly", 02356 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE); 02357 netsnmp_ds_register_premib(ASN_BOOLEAN, "snmp", "dontPrintUnits", 02358 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS); 02359 netsnmp_ds_register_premib(ASN_INTEGER, "snmp", "hexOutputLength", 02360 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_HEX_OUTPUT_LENGTH); 02361 } 02362 02363 #ifndef NETSNMP_DISABLE_MIB_LOADING 02364 /* 02365 * function : netsnmp_set_mib_directory 02366 * - This function sets the string of the directories 02367 * from which the MIB modules will be searched or 02368 * loaded. 02369 * arguments: const char *dir, which are the directories 02370 * from which the MIB modules will be searched or 02371 * loaded. 02372 * returns : - 02373 */ 02374 void 02375 netsnmp_set_mib_directory(const char *dir) 02376 { 02377 const char *newdir; 02378 char *olddir, *tmpdir = NULL; 02379 02380 DEBUGTRACE; 02381 if (NULL == dir) { 02382 return; 02383 } 02384 02385 olddir = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 02386 NETSNMP_DS_LIB_MIBDIRS); 02387 if (olddir) { 02388 if ((*dir == '+') || (*dir == '-')) { 02390 tmpdir = (char *)malloc(strlen(dir) + strlen(olddir) + 2); 02391 if (!tmpdir) { 02392 DEBUGMSGTL(("read_config:initmib", "set mibdir malloc failed")); 02393 return; 02394 } 02395 if (*dir++ == '+') 02396 sprintf(tmpdir, "%s%c%s", olddir, ENV_SEPARATOR_CHAR, dir); 02397 else 02398 sprintf(tmpdir, "%s%c%s", dir, ENV_SEPARATOR_CHAR, olddir); 02399 newdir = tmpdir; 02400 } else { 02401 newdir = dir; 02402 } 02403 } else { 02405 newdir = ((*dir == '+') ? ++dir : dir); 02406 } 02407 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS, 02408 newdir); 02409 02411 if (tmpdir == newdir) { 02412 SNMP_FREE(tmpdir); 02413 } 02414 } 02415 02416 /* 02417 * function : netsnmp_get_mib_directory 02418 * - This function returns a string of the directories 02419 * from which the MIB modules will be searched or 02420 * loaded. 02421 * If the value still does not exists, it will be made 02422 * from the evironment variable 'MIBDIRS' and/or the 02423 * default. 02424 * arguments: - 02425 * returns : char * of the directories in which the MIB modules 02426 * will be searched/loaded. 02427 */ 02428 02429 char * 02430 netsnmp_get_mib_directory(void) 02431 { 02432 char *dir; 02433 02434 DEBUGTRACE; 02435 dir = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS); 02436 if (dir == NULL) { 02437 DEBUGMSGTL(("get_mib_directory", "no mib directories set\n")); 02438 02440 dir = netsnmp_getenv("MIBDIRS"); 02441 if (dir == NULL) { 02442 DEBUGMSGTL(("get_mib_directory", "no mib directories set by environment\n")); 02444 if (confmibdir == NULL) { 02445 DEBUGMSGTL(("get_mib_directory", "no mib directories set by config\n")); 02446 netsnmp_set_mib_directory(NETSNMP_DEFAULT_MIBDIRS); 02447 } 02448 else if ((*confmibdir == '+') || (*confmibdir == '-')) { 02449 DEBUGMSGTL(("get_mib_directory", "mib directories set by config (but added)\n")); 02450 netsnmp_set_mib_directory(NETSNMP_DEFAULT_MIBDIRS); 02451 netsnmp_set_mib_directory(confmibdir); 02452 } 02453 else { 02454 DEBUGMSGTL(("get_mib_directory", "mib directories set by config\n")); 02455 netsnmp_set_mib_directory(confmibdir); 02456 } 02457 } else if ((*dir == '+') || (*dir == '-')) { 02458 DEBUGMSGTL(("get_mib_directory", "mib directories set by environment (but added)\n")); 02459 netsnmp_set_mib_directory(NETSNMP_DEFAULT_MIBDIRS); 02460 netsnmp_set_mib_directory(dir); 02461 } else { 02462 DEBUGMSGTL(("get_mib_directory", "mib directories set by environment\n")); 02463 netsnmp_set_mib_directory(dir); 02464 } 02465 dir = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIBDIRS); 02466 } 02467 DEBUGMSGTL(("get_mib_directory", "mib directories set '%s'\n", dir)); 02468 return(dir); 02469 } 02470 02471 /* 02472 * function : netsnmp_fixup_mib_directory 02473 * arguments: - 02474 * returns : - 02475 */ 02476 void 02477 netsnmp_fixup_mib_directory(void) 02478 { 02479 char *homepath = netsnmp_getenv("HOME"); 02480 char *mibpath = netsnmp_get_mib_directory(); 02481 char *oldmibpath = NULL; 02482 char *ptr_home; 02483 char *new_mibpath; 02484 02485 DEBUGTRACE; 02486 if (homepath && mibpath) { 02487 DEBUGMSGTL(("fixup_mib_directory", "mib directories '%s'\n", mibpath)); 02488 while ((ptr_home = strstr(mibpath, "$HOME"))) { 02489 new_mibpath = (char *)malloc(strlen(mibpath) - strlen("$HOME") + 02490 strlen(homepath)+1); 02491 if (new_mibpath) { 02492 *ptr_home = 0; /* null out the spot where we stop copying */ 02493 sprintf(new_mibpath, "%s%s%s", mibpath, homepath, 02494 ptr_home + strlen("$HOME")); 02496 mibpath = new_mibpath; 02497 if (oldmibpath != NULL) { 02498 SNMP_FREE(oldmibpath); 02499 } 02500 oldmibpath = new_mibpath; 02501 } else { 02502 break; 02503 } 02504 } 02505 02506 netsnmp_set_mib_directory(mibpath); 02507 02508 /* The above copies the mibpath for us, so... */ 02509 02510 if (oldmibpath != NULL) { 02511 SNMP_FREE(oldmibpath); 02512 } 02513 02514 } 02515 02516 } 02517 02523 void 02524 netsnmp_init_mib(void) 02525 { 02526 const char *prefix; 02527 char *env_var, *entry; 02528 PrefixListPtr pp = &mib_prefixes[0]; 02529 char *st = NULL; 02530 02531 if (Mib) 02532 return; 02533 netsnmp_init_mib_internals(); 02534 02535 /* 02536 * Initialise the MIB directory/ies 02537 */ 02538 netsnmp_fixup_mib_directory(); 02539 env_var = strdup(netsnmp_get_mib_directory()); 02540 02541 DEBUGMSGTL(("init_mib", 02542 "Seen MIBDIRS: Looking in '%s' for mib dirs ...\n", 02543 env_var)); 02544 02545 entry = strtok_r(env_var, ENV_SEPARATOR, &st); 02546 while (entry) { 02547 add_mibdir(entry); 02548 entry = strtok_r(NULL, ENV_SEPARATOR, &st); 02549 } 02550 SNMP_FREE(env_var); 02551 02552 env_var = netsnmp_getenv("MIBFILES"); 02553 if (env_var != NULL) { 02554 if (*env_var == '+') 02555 entry = strtok_r(env_var+1, ENV_SEPARATOR, &st); 02556 else 02557 entry = strtok_r(env_var, ENV_SEPARATOR, &st); 02558 while (entry) { 02559 add_mibfile(entry, NULL, NULL); 02560 entry = strtok_r(NULL, ENV_SEPARATOR, &st); 02561 } 02562 } 02563 02564 netsnmp_init_mib_internals(); 02565 02566 /* 02567 * Read in any modules or mibs requested 02568 */ 02569 02570 env_var = netsnmp_getenv("MIBS"); 02571 if (env_var == NULL) { 02572 if (confmibs != NULL) 02573 env_var = strdup(confmibs); 02574 else 02575 env_var = strdup(NETSNMP_DEFAULT_MIBS); 02576 } else { 02577 env_var = strdup(env_var); 02578 } 02579 if (env_var && ((*env_var == '+') || (*env_var == '-'))) { 02580 entry = 02581 (char *) malloc(strlen(NETSNMP_DEFAULT_MIBS) + strlen(env_var) + 2); 02582 if (!entry) { 02583 DEBUGMSGTL(("init_mib", "env mibs malloc failed")); 02584 SNMP_FREE(env_var); 02585 return; 02586 } else { 02587 if (*env_var == '+') 02588 sprintf(entry, "%s%c%s", NETSNMP_DEFAULT_MIBS, ENV_SEPARATOR_CHAR, 02589 env_var+1); 02590 else 02591 sprintf(entry, "%s%c%s", env_var+1, ENV_SEPARATOR_CHAR, 02592 NETSNMP_DEFAULT_MIBS ); 02593 } 02594 SNMP_FREE(env_var); 02595 env_var = entry; 02596 } 02597 02598 DEBUGMSGTL(("init_mib", 02599 "Seen MIBS: Looking in '%s' for mib files ...\n", 02600 env_var)); 02601 entry = strtok_r(env_var, ENV_SEPARATOR, &st); 02602 while (entry) { 02603 if (strcasecmp(entry, DEBUG_ALWAYS_TOKEN) == 0) { 02604 read_all_mibs(); 02605 } else if (strstr(entry, "/") != 0) { 02606 read_mib(entry); 02607 } else { 02608 netsnmp_read_module(entry); 02609 } 02610 entry = strtok_r(NULL, ENV_SEPARATOR, &st); 02611 } 02612 adopt_orphans(); 02613 SNMP_FREE(env_var); 02614 02615 env_var = netsnmp_getenv("MIBFILES"); 02616 if (env_var != NULL) { 02617 if ((*env_var == '+') || (*env_var == '-')) { 02618 #ifdef NETSNMP_DEFAULT_MIBFILES 02619 entry = 02620 (char *) malloc(strlen(NETSNMP_DEFAULT_MIBFILES) + 02621 strlen(env_var) + 2); 02622 if (!entry) { 02623 DEBUGMSGTL(("init_mib", "env mibfiles malloc failed")); 02624 } else { 02625 if (*env_var++ == '+') 02626 sprintf(entry, "%s%c%s", NETSNMP_DEFAULT_MIBFILES, ENV_SEPARATOR_CHAR, 02627 env_var ); 02628 else 02629 sprintf(entry, "%s%c%s", env_var, ENV_SEPARATOR_CHAR, 02630 NETSNMP_DEFAULT_MIBFILES ); 02631 } 02632 SNMP_FREE(env_var); 02633 env_var = entry; 02634 #else 02635 env_var = strdup(env_var + 1); 02636 #endif 02637 } else { 02638 env_var = strdup(env_var); 02639 } 02640 } else { 02641 #ifdef NETSNMP_DEFAULT_MIBFILES 02642 env_var = strdup(NETSNMP_DEFAULT_MIBFILES); 02643 #endif 02644 } 02645 02646 if (env_var != 0) { 02647 DEBUGMSGTL(("init_mib", 02648 "Seen MIBFILES: Looking in '%s' for mib files ...\n", 02649 env_var)); 02650 entry = strtok_r(env_var, ENV_SEPARATOR, &st); 02651 while (entry) { 02652 read_mib(entry); 02653 entry = strtok_r(NULL, ENV_SEPARATOR, &st); 02654 } 02655 SNMP_FREE(env_var); 02656 } 02657 02658 prefix = netsnmp_getenv("PREFIX"); 02659 02660 if (!prefix) 02661 prefix = Standard_Prefix; 02662 02663 Prefix = (char *) malloc(strlen(prefix) + 2); 02664 if (!Prefix) 02665 DEBUGMSGTL(("init_mib", "Prefix malloc failed")); 02666 else 02667 strcpy(Prefix, prefix); 02668 02669 DEBUGMSGTL(("init_mib", 02670 "Seen PREFIX: Looking in '%s' for prefix ...\n", Prefix)); 02671 02672 /* 02673 * remove trailing dot 02674 */ 02675 if (Prefix) { 02676 env_var = &Prefix[strlen(Prefix) - 1]; 02677 if (*env_var == '.') 02678 *env_var = '\0'; 02679 } 02680 02681 pp->str = Prefix; /* fixup first mib_prefix entry */ 02682 /* 02683 * now that the list of prefixes is built, save each string length. 02684 */ 02685 while (pp->str) { 02686 pp->len = strlen(pp->str); 02687 pp++; 02688 } 02689 02690 Mib = tree_head; /* Backwards compatibility */ 02691 tree_top = (struct tree *) calloc(1, sizeof(struct tree)); 02692 /* 02693 * XX error check ? 02694 */ 02695 if (tree_top) { 02696 tree_top->label = strdup("(top)"); 02697 tree_top->child_list = tree_head; 02698 } 02699 } 02700 02701 #ifndef NETSNMP_CLEAN_NAMESPACE 02702 void 02703 init_mib(void) 02704 { 02705 netsnmp_init_mib(); 02706 } 02707 #endif 02708 02709 02713 void 02714 shutdown_mib(void) 02715 { 02716 unload_all_mibs(); 02717 if (tree_top) { 02718 if (tree_top->label) 02719 SNMP_FREE(tree_top->label); 02720 SNMP_FREE(tree_top); 02721 tree_top = NULL; 02722 } 02723 tree_head = NULL; 02724 Mib = NULL; 02725 if (Prefix != NULL && Prefix != &Standard_Prefix[0]) 02726 SNMP_FREE(Prefix); 02727 if (Prefix) 02728 Prefix = NULL; 02729 SNMP_FREE(confmibs); 02730 SNMP_FREE(confmibdir); 02731 } 02732 02738 void 02739 print_mib(FILE * fp) 02740 { 02741 print_subtree(fp, tree_head, 0); 02742 } 02743 02744 void 02745 print_ascii_dump(FILE * fp) 02746 { 02747 fprintf(fp, "dump DEFINITIONS ::= BEGIN\n"); 02748 print_ascii_dump_tree(fp, tree_head, 0); 02749 fprintf(fp, "END\n"); 02750 } 02751 02752 02759 void 02760 set_function(struct tree *subtree) 02761 { 02762 subtree->printer = NULL; 02763 switch (subtree->type) { 02764 case TYPE_OBJID: 02765 subtree->printomat = sprint_realloc_object_identifier; 02766 break; 02767 case TYPE_OCTETSTR: 02768 subtree->printomat = sprint_realloc_octet_string; 02769 break; 02770 case TYPE_INTEGER: 02771 subtree->printomat = sprint_realloc_integer; 02772 break; 02773 case TYPE_INTEGER32: 02774 subtree->printomat = sprint_realloc_integer; 02775 break; 02776 case TYPE_NETADDR: 02777 subtree->printomat = sprint_realloc_networkaddress; 02778 break; 02779 case TYPE_IPADDR: 02780 subtree->printomat = sprint_realloc_ipaddress; 02781 break; 02782 case TYPE_COUNTER: 02783 subtree->printomat = sprint_realloc_counter; 02784 break; 02785 case TYPE_GAUGE: 02786 subtree->printomat = sprint_realloc_gauge; 02787 break; 02788 case TYPE_TIMETICKS: 02789 subtree->printomat = sprint_realloc_timeticks; 02790 break; 02791 case TYPE_OPAQUE: 02792 subtree->printomat = sprint_realloc_opaque; 02793 break; 02794 case TYPE_NULL: 02795 subtree->printomat = sprint_realloc_null; 02796 break; 02797 case TYPE_BITSTRING: 02798 subtree->printomat = sprint_realloc_bitstring; 02799 break; 02800 case TYPE_NSAPADDRESS: 02801 subtree->printomat = sprint_realloc_nsapaddress; 02802 break; 02803 case TYPE_COUNTER64: 02804 subtree->printomat = sprint_realloc_counter64; 02805 break; 02806 case TYPE_UINTEGER: 02807 subtree->printomat = sprint_realloc_uinteger; 02808 break; 02809 case TYPE_UNSIGNED32: 02810 subtree->printomat = sprint_realloc_gauge; 02811 break; 02812 case TYPE_OTHER: 02813 default: 02814 subtree->printomat = sprint_realloc_by_type; 02815 break; 02816 } 02817 } 02818 02819 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 02820 02836 int 02837 read_objid(const char *input, oid * output, size_t * out_len) 02838 { /* number of subid's in "output" */ 02839 #ifndef NETSNMP_DISABLE_MIB_LOADING 02840 struct tree *root = tree_top; 02841 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 02842 char buf[SPRINT_MAX_LEN]; 02843 int ret, max_out_len; 02844 char *name, ch; 02845 const char *cp; 02846 02847 cp = input; 02848 while ((ch = *cp)) { 02849 if (('0' <= ch && ch <= '9') 02850 || ('a' <= ch && ch <= 'z') 02851 || ('A' <= ch && ch <= 'Z') 02852 || ch == '-') 02853 cp++; 02854 else 02855 break; 02856 } 02857 #ifndef NETSNMP_DISABLE_MIB_LOADING 02858 if (ch == ':') 02859 return get_node(input, output, out_len); 02860 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 02861 02862 if (*input == '.') 02863 input++; 02864 #ifndef NETSNMP_DISABLE_MIB_LOADING 02865 else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_READ_UCD_STYLE_OID)) { 02866 /* 02867 * get past leading '.', append '.' to Prefix. 02868 */ 02869 if (*Prefix == '.') 02870 strncpy(buf, Prefix + 1, sizeof(buf)-1); 02871 else 02872 strncpy(buf, Prefix, sizeof(buf)-1); 02873 buf[ sizeof(buf)-1 ] = 0; 02874 strcat(buf, "."); 02875 buf[ sizeof(buf)-1 ] = 0; 02876 strncat(buf, input, sizeof(buf)-strlen(buf)); 02877 buf[ sizeof(buf)-1 ] = 0; 02878 input = buf; 02879 } 02880 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 02881 02882 #ifndef NETSNMP_DISABLE_MIB_LOADING 02883 if ((root == NULL) && (tree_head != NULL)) { 02884 root = tree_head; 02885 } 02886 else if (root == NULL) { 02887 SET_SNMP_ERROR(SNMPERR_NOMIB); 02888 *out_len = 0; 02889 return 0; 02890 } 02891 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 02892 name = strdup(input); 02893 max_out_len = *out_len; 02894 *out_len = 0; 02895 #ifndef NETSNMP_DISABLE_MIB_LOADING 02896 if ((ret = 02897 _add_strings_to_oid(root, name, output, out_len, 02898 max_out_len)) <= 0) 02899 #else 02900 if ((ret = 02901 _add_strings_to_oid(NULL, name, output, out_len, 02902 max_out_len)) <= 0) 02903 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 02904 { 02905 if (ret == 0) 02906 ret = SNMPERR_UNKNOWN_OBJID; 02907 SET_SNMP_ERROR(ret); 02908 SNMP_FREE(name); 02909 return 0; 02910 } 02911 SNMP_FREE(name); 02912 02913 return 1; 02914 } 02915 02919 void 02920 netsnmp_sprint_realloc_objid(u_char ** buf, size_t * buf_len, 02921 size_t * out_len, int allow_realloc, 02922 int *buf_overflow, 02923 const oid * objid, size_t objidlen) 02924 { 02925 u_char *tbuf = NULL, *cp = NULL; 02926 size_t tbuf_len = 256, tout_len = 0; 02927 int tbuf_overflow = 0; 02928 int output_format; 02929 02930 if ((tbuf = (u_char *) calloc(tbuf_len, 1)) == NULL) { 02931 tbuf_overflow = 1; 02932 } else { 02933 *tbuf = '.'; 02934 tout_len = 1; 02935 } 02936 02937 _oid_finish_printing(objid, objidlen, 02938 &tbuf, &tbuf_len, &tout_len, 02939 allow_realloc, &tbuf_overflow); 02940 02941 if (tbuf_overflow) { 02942 if (!*buf_overflow) { 02943 snmp_strcat(buf, buf_len, out_len, allow_realloc, tbuf); 02944 *buf_overflow = 1; 02945 } 02946 SNMP_FREE(tbuf); 02947 return; 02948 } 02949 02950 output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT); 02951 if (0 == output_format) { 02952 output_format = NETSNMP_OID_OUTPUT_NUMERIC; 02953 } 02954 switch (output_format) { 02955 case NETSNMP_OID_OUTPUT_FULL: 02956 case NETSNMP_OID_OUTPUT_NUMERIC: 02957 case NETSNMP_OID_OUTPUT_SUFFIX: 02958 case NETSNMP_OID_OUTPUT_MODULE: 02959 cp = tbuf; 02960 break; 02961 02962 case NETSNMP_OID_OUTPUT_NONE: 02963 default: 02964 cp = NULL; 02965 } 02966 02967 if (!*buf_overflow && 02968 !snmp_strcat(buf, buf_len, out_len, allow_realloc, cp)) { 02969 *buf_overflow = 1; 02970 } 02971 SNMP_FREE(tbuf); 02972 } 02973 02977 #ifdef NETSNMP_DISABLE_MIB_LOADING 02978 void 02979 netsnmp_sprint_realloc_objid_tree(u_char ** buf, size_t * buf_len, 02980 size_t * out_len, int allow_realloc, 02981 int *buf_overflow, 02982 const oid * objid, size_t objidlen) 02983 { 02984 netsnmp_sprint_realloc_objid(buf, buf_len, out_len, allow_realloc, 02985 buf_overflow, objid, objidlen); 02986 } 02987 #else 02988 struct tree * 02989 netsnmp_sprint_realloc_objid_tree(u_char ** buf, size_t * buf_len, 02990 size_t * out_len, int allow_realloc, 02991 int *buf_overflow, 02992 const oid * objid, size_t objidlen) 02993 { 02994 u_char *tbuf = NULL, *cp = NULL; 02995 size_t tbuf_len = 512, tout_len = 0; 02996 struct tree *subtree = tree_head; 02997 size_t midpoint_offset = 0; 02998 int tbuf_overflow = 0; 02999 int output_format; 03000 03001 if ((tbuf = (u_char *) calloc(tbuf_len, 1)) == NULL) { 03002 tbuf_overflow = 1; 03003 } else { 03004 *tbuf = '.'; 03005 tout_len = 1; 03006 } 03007 03008 subtree = _get_realloc_symbol(objid, objidlen, subtree, 03009 &tbuf, &tbuf_len, &tout_len, 03010 allow_realloc, &tbuf_overflow, NULL, 03011 &midpoint_offset); 03012 03013 if (tbuf_overflow) { 03014 if (!*buf_overflow) { 03015 snmp_strcat(buf, buf_len, out_len, allow_realloc, tbuf); 03016 *buf_overflow = 1; 03017 } 03018 SNMP_FREE(tbuf); 03019 return subtree; 03020 } 03021 03022 output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT); 03023 if (0 == output_format) { 03024 output_format = NETSNMP_OID_OUTPUT_MODULE; 03025 } 03026 switch (output_format) { 03027 case NETSNMP_OID_OUTPUT_FULL: 03028 case NETSNMP_OID_OUTPUT_NUMERIC: 03029 cp = tbuf; 03030 break; 03031 03032 case NETSNMP_OID_OUTPUT_SUFFIX: 03033 case NETSNMP_OID_OUTPUT_MODULE: 03034 for (cp = tbuf; *cp; cp++); 03035 03036 if (midpoint_offset != 0) { 03037 cp = tbuf + midpoint_offset - 2; /* beyond the '.' */ 03038 } else { 03039 while (cp >= tbuf) { 03040 if (isalpha(*cp)) { 03041 break; 03042 } 03043 cp--; 03044 } 03045 } 03046 03047 while (cp >= tbuf) { 03048 if (*cp == '.') { 03049 break; 03050 } 03051 cp--; 03052 } 03053 03054 cp++; 03055 03056 if ((NETSNMP_OID_OUTPUT_MODULE == output_format) 03057 && cp > tbuf) { 03058 char modbuf[256] = { 0 }, *mod = 03059 module_name(subtree->modid, modbuf); 03060 03061 /* 03062 * Don't add the module ID if it's just numeric (i.e. we couldn't look 03063 * it up properly. 03064 */ 03065 03066 if (!*buf_overflow && modbuf[0] != '#') { 03067 if (!snmp_strcat 03068 (buf, buf_len, out_len, allow_realloc, 03069 (const u_char *) mod) 03070 || !snmp_strcat(buf, buf_len, out_len, allow_realloc, 03071 (const u_char *) "::")) { 03072 *buf_overflow = 1; 03073 } 03074 } 03075 } 03076 break; 03077 03078 case NETSNMP_OID_OUTPUT_UCD: 03079 { 03080 PrefixListPtr pp = &mib_prefixes[0]; 03081 size_t ilen, tlen; 03082 const char *testcp; 03083 03084 cp = tbuf; 03085 tlen = strlen((char *) tbuf); 03086 03087 while (pp->str) { 03088 ilen = pp->len; 03089 testcp = pp->str; 03090 03091 if ((tlen > ilen) && memcmp(tbuf, testcp, ilen) == 0) { 03092 cp += (ilen + 1); 03093 break; 03094 } 03095 pp++; 03096 } 03097 break; 03098 } 03099 03100 case NETSNMP_OID_OUTPUT_NONE: 03101 default: 03102 cp = NULL; 03103 } 03104 03105 if (!*buf_overflow && 03106 !snmp_strcat(buf, buf_len, out_len, allow_realloc, cp)) { 03107 *buf_overflow = 1; 03108 } 03109 SNMP_FREE(tbuf); 03110 return subtree; 03111 } 03112 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 03113 03114 int 03115 sprint_realloc_objid(u_char ** buf, size_t * buf_len, 03116 size_t * out_len, int allow_realloc, 03117 const oid * objid, size_t objidlen) 03118 { 03119 int buf_overflow = 0; 03120 03121 netsnmp_sprint_realloc_objid_tree(buf, buf_len, out_len, allow_realloc, 03122 &buf_overflow, objid, objidlen); 03123 return !buf_overflow; 03124 } 03125 03126 int 03127 snprint_objid(char *buf, size_t buf_len, 03128 const oid * objid, size_t objidlen) 03129 { 03130 size_t out_len = 0; 03131 03132 if (sprint_realloc_objid((u_char **) & buf, &buf_len, &out_len, 0, 03133 objid, objidlen)) { 03134 return (int) out_len; 03135 } else { 03136 return -1; 03137 } 03138 } 03139 03146 void 03147 print_objid(const oid * objid, size_t objidlen) 03148 { /* number of subidentifiers */ 03149 fprint_objid(stdout, objid, objidlen); 03150 } 03151 03152 03160 void 03161 fprint_objid(FILE * f, const oid * objid, size_t objidlen) 03162 { /* number of subidentifiers */ 03163 u_char *buf = NULL; 03164 size_t buf_len = 256, out_len = 0; 03165 int buf_overflow = 0; 03166 03167 if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) { 03168 fprintf(f, "[TRUNCATED]\n"); 03169 return; 03170 } else { 03171 netsnmp_sprint_realloc_objid_tree(&buf, &buf_len, &out_len, 1, 03172 &buf_overflow, objid, objidlen); 03173 if (buf_overflow) { 03174 fprintf(f, "%s [TRUNCATED]\n", buf); 03175 } else { 03176 fprintf(f, "%s\n", buf); 03177 } 03178 } 03179 03180 SNMP_FREE(buf); 03181 } 03182 03183 int 03184 sprint_realloc_variable(u_char ** buf, size_t * buf_len, 03185 size_t * out_len, int allow_realloc, 03186 const oid * objid, size_t objidlen, 03187 const netsnmp_variable_list * variable) 03188 { 03189 int buf_overflow = 0; 03190 03191 #ifndef NETSNMP_DISABLE_MIB_LOADING 03192 struct tree *subtree = tree_head; 03193 03194 subtree = 03195 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 03196 netsnmp_sprint_realloc_objid_tree(buf, buf_len, out_len, 03197 allow_realloc, &buf_overflow, 03198 objid, objidlen); 03199 03200 if (buf_overflow) { 03201 return 0; 03202 } 03203 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE)) { 03204 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT)) { 03205 if (!snmp_strcat 03206 (buf, buf_len, out_len, allow_realloc, 03207 (const u_char *) " = ")) { 03208 return 0; 03209 } 03210 } else { 03211 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT)) { 03212 if (!snmp_strcat 03213 (buf, buf_len, out_len, allow_realloc, 03214 (const u_char *) " ")) { 03215 return 0; 03216 } 03217 } else { 03218 if (!snmp_strcat 03219 (buf, buf_len, out_len, allow_realloc, 03220 (const u_char *) " = ")) { 03221 return 0; 03222 } 03223 } /* end if-else NETSNMP_DS_LIB_QUICK_PRINT */ 03224 } /* end if-else NETSNMP_DS_LIB_QUICKE_PRINT */ 03225 } else { 03226 *out_len = 0; 03227 } 03228 03229 if (variable->type == SNMP_NOSUCHOBJECT) { 03230 return snmp_strcat(buf, buf_len, out_len, allow_realloc, 03231 (const u_char *) 03232 "No Such Object available on this agent at this OID"); 03233 } else if (variable->type == SNMP_NOSUCHINSTANCE) { 03234 return snmp_strcat(buf, buf_len, out_len, allow_realloc, 03235 (const u_char *) 03236 "No Such Instance currently exists at this OID"); 03237 } else if (variable->type == SNMP_ENDOFMIBVIEW) { 03238 return snmp_strcat(buf, buf_len, out_len, allow_realloc, 03239 (const u_char *) 03240 "No more variables left in this MIB View (It is past the end of the MIB tree)"); 03241 #ifndef NETSNMP_DISABLE_MIB_LOADING 03242 } else if (subtree) { 03243 const char *units = NULL; 03244 if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 03245 NETSNMP_DS_LIB_DONT_PRINT_UNITS)) { 03246 units = subtree->units; 03247 } 03248 if (subtree->printomat) { 03249 return (*subtree->printomat) (buf, buf_len, out_len, 03250 allow_realloc, variable, 03251 subtree->enums, subtree->hint, 03252 units); 03253 } else { 03254 return sprint_realloc_by_type(buf, buf_len, out_len, 03255 allow_realloc, variable, 03256 subtree->enums, subtree->hint, 03257 units); 03258 } 03259 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 03260 } else { 03261 /* 03262 * Handle rare case where tree is empty. 03263 */ 03264 return sprint_realloc_by_type(buf, buf_len, out_len, allow_realloc, 03265 variable, 0, 0, 0); 03266 } 03267 } 03268 03269 int 03270 snprint_variable(char *buf, size_t buf_len, 03271 const oid * objid, size_t objidlen, 03272 const netsnmp_variable_list * variable) 03273 { 03274 size_t out_len = 0; 03275 03276 if (sprint_realloc_variable((u_char **) & buf, &buf_len, &out_len, 0, 03277 objid, objidlen, variable)) { 03278 return (int) out_len; 03279 } else { 03280 return -1; 03281 } 03282 } 03283 03291 void 03292 print_variable(const oid * objid, 03293 size_t objidlen, const netsnmp_variable_list * variable) 03294 { 03295 fprint_variable(stdout, objid, objidlen, variable); 03296 } 03297 03298 03307 void 03308 fprint_variable(FILE * f, 03309 const oid * objid, 03310 size_t objidlen, const netsnmp_variable_list * variable) 03311 { 03312 u_char *buf = NULL; 03313 size_t buf_len = 256, out_len = 0; 03314 03315 if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) { 03316 fprintf(f, "[TRUNCATED]\n"); 03317 return; 03318 } else { 03319 if (sprint_realloc_variable(&buf, &buf_len, &out_len, 1, 03320 objid, objidlen, variable)) { 03321 fprintf(f, "%s\n", buf); 03322 } else { 03323 fprintf(f, "%s [TRUNCATED]\n", buf); 03324 } 03325 } 03326 03327 SNMP_FREE(buf); 03328 } 03329 03330 int 03331 sprint_realloc_value(u_char ** buf, size_t * buf_len, 03332 size_t * out_len, int allow_realloc, 03333 const oid * objid, size_t objidlen, 03334 const netsnmp_variable_list * variable) 03335 { 03336 #ifndef NETSNMP_DISABLE_MIB_LOADING 03337 struct tree *subtree = tree_head; 03338 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 03339 03340 if (variable->type == SNMP_NOSUCHOBJECT) { 03341 return snmp_strcat(buf, buf_len, out_len, allow_realloc, 03342 (const u_char *) 03343 "No Such Object available on this agent at this OID"); 03344 } else if (variable->type == SNMP_NOSUCHINSTANCE) { 03345 return snmp_strcat(buf, buf_len, out_len, allow_realloc, 03346 (const u_char *) 03347 "No Such Instance currently exists at this OID"); 03348 } else if (variable->type == SNMP_ENDOFMIBVIEW) { 03349 return snmp_strcat(buf, buf_len, out_len, allow_realloc, 03350 (const u_char *) 03351 "No more variables left in this MIB View (It is past the end of the MIB tree)"); 03352 } else { 03353 #ifndef NETSNMP_DISABLE_MIB_LOADING 03354 const char *units = NULL; 03355 subtree = get_tree(objid, objidlen, subtree); 03356 if (subtree && !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 03357 NETSNMP_DS_LIB_DONT_PRINT_UNITS)) { 03358 units = subtree->units; 03359 } 03360 if (subtree && subtree->printomat) { 03361 return (*subtree->printomat) (buf, buf_len, out_len, 03362 allow_realloc, variable, 03363 subtree->enums, subtree->hint, 03364 units); 03365 } else { 03366 return sprint_realloc_by_type(buf, buf_len, out_len, 03367 allow_realloc, variable, 03368 subtree->enums, subtree->hint, 03369 units); 03370 } 03371 #else 03372 return sprint_realloc_by_type(buf, buf_len, out_len, 03373 allow_realloc, variable, 03374 NULL, NULL, NULL); 03375 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 03376 } 03377 } 03378 03379 int 03380 snprint_value(char *buf, size_t buf_len, 03381 const oid * objid, size_t objidlen, 03382 const netsnmp_variable_list * variable) 03383 { 03384 size_t out_len = 0; 03385 03386 if (sprint_realloc_value((u_char **) & buf, &buf_len, &out_len, 0, 03387 objid, objidlen, variable)) { 03388 return (int) out_len; 03389 } else { 03390 return -1; 03391 } 03392 } 03393 03394 void 03395 print_value(const oid * objid, 03396 size_t objidlen, const netsnmp_variable_list * variable) 03397 { 03398 fprint_value(stdout, objid, objidlen, variable); 03399 } 03400 03401 void 03402 fprint_value(FILE * f, 03403 const oid * objid, 03404 size_t objidlen, const netsnmp_variable_list * variable) 03405 { 03406 u_char *buf = NULL; 03407 size_t buf_len = 256, out_len = 0; 03408 03409 if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) { 03410 fprintf(f, "[TRUNCATED]\n"); 03411 return; 03412 } else { 03413 if (sprint_realloc_value(&buf, &buf_len, &out_len, 1, 03414 objid, objidlen, variable)) { 03415 fprintf(f, "%s\n", buf); 03416 } else { 03417 fprintf(f, "%s [TRUNCATED]\n", buf); 03418 } 03419 } 03420 03421 SNMP_FREE(buf); 03422 } 03423 03424 03432 int 03433 build_oid_segment(netsnmp_variable_list * var) 03434 { 03435 int i; 03436 03437 if (var->name && var->name != var->name_loc) 03438 SNMP_FREE(var->name); 03439 switch (var->type) { 03440 case ASN_INTEGER: 03441 case ASN_COUNTER: 03442 case ASN_GAUGE: 03443 case ASN_TIMETICKS: 03444 var->name_length = 1; 03445 var->name = var->name_loc; 03446 var->name[0] = *(var->val.integer); 03447 break; 03448 03449 case ASN_IPADDRESS: 03450 var->name_length = 4; 03451 var->name = var->name_loc; 03452 var->name[0] = 03453 (((unsigned int) *(var->val.integer)) & 0xff000000) >> 24; 03454 var->name[1] = 03455 (((unsigned int) *(var->val.integer)) & 0x00ff0000) >> 16; 03456 var->name[2] = 03457 (((unsigned int) *(var->val.integer)) & 0x0000ff00) >> 8; 03458 var->name[3] = 03459 (((unsigned int) *(var->val.integer)) & 0x000000ff); 03460 break; 03461 03462 case ASN_PRIV_IMPLIED_OBJECT_ID: 03463 var->name_length = var->val_len / sizeof(oid); 03464 if (var->name_length > (sizeof(var->name_loc) / sizeof(oid))) 03465 var->name = (oid *) malloc(sizeof(oid) * (var->name_length)); 03466 else 03467 var->name = var->name_loc; 03468 if (var->name == NULL) 03469 return SNMPERR_GENERR; 03470 03471 for (i = 0; i < (int) var->name_length; i++) 03472 var->name[i] = var->val.objid[i]; 03473 break; 03474 03475 case ASN_OBJECT_ID: 03476 var->name_length = var->val_len / sizeof(oid) + 1; 03477 if (var->name_length > (sizeof(var->name_loc) / sizeof(oid))) 03478 var->name = (oid *) malloc(sizeof(oid) * (var->name_length)); 03479 else 03480 var->name = var->name_loc; 03481 if (var->name == NULL) 03482 return SNMPERR_GENERR; 03483 03484 var->name[0] = var->name_length - 1; 03485 for (i = 0; i < (int) var->name_length - 1; i++) 03486 var->name[i + 1] = var->val.objid[i]; 03487 break; 03488 03489 case ASN_PRIV_IMPLIED_OCTET_STR: 03490 var->name_length = var->val_len; 03491 if (var->name_length > (sizeof(var->name_loc) / sizeof(oid))) 03492 var->name = (oid *) malloc(sizeof(oid) * (var->name_length)); 03493 else 03494 var->name = var->name_loc; 03495 if (var->name == NULL) 03496 return SNMPERR_GENERR; 03497 03498 for (i = 0; i < (int) var->val_len; i++) 03499 var->name[i] = (oid) var->val.string[i]; 03500 break; 03501 03502 case ASN_OPAQUE: 03503 case ASN_OCTET_STR: 03504 var->name_length = var->val_len + 1; 03505 if (var->name_length > (sizeof(var->name_loc) / sizeof(oid))) 03506 var->name = (oid *) malloc(sizeof(oid) * (var->name_length)); 03507 else 03508 var->name = var->name_loc; 03509 if (var->name == NULL) 03510 return SNMPERR_GENERR; 03511 03512 var->name[0] = (oid) var->val_len; 03513 for (i = 0; i < (int) var->val_len; i++) 03514 var->name[i + 1] = (oid) var->val.string[i]; 03515 break; 03516 03517 default: 03518 DEBUGMSGTL(("build_oid_segment", 03519 "invalid asn type: %d\n", var->type)); 03520 return SNMPERR_GENERR; 03521 } 03522 03523 if (var->name_length > MAX_OID_LEN) { 03524 DEBUGMSGTL(("build_oid_segment", 03525 "Something terribly wrong, namelen = %d\n", 03526 var->name_length)); 03527 return SNMPERR_GENERR; 03528 } 03529 03530 return SNMPERR_SUCCESS; 03531 } 03532 03533 03534 int 03535 build_oid_noalloc(oid * in, size_t in_len, size_t * out_len, 03536 oid * prefix, size_t prefix_len, 03537 netsnmp_variable_list * indexes) 03538 { 03539 netsnmp_variable_list *var; 03540 03541 if (prefix) { 03542 if (in_len < prefix_len) 03543 return SNMPERR_GENERR; 03544 memcpy(in, prefix, prefix_len * sizeof(oid)); 03545 *out_len = prefix_len; 03546 } else { 03547 *out_len = 0; 03548 } 03549 03550 for (var = indexes; var != NULL; var = var->next_variable) { 03551 if (build_oid_segment(var) != SNMPERR_SUCCESS) 03552 return SNMPERR_GENERR; 03553 if (var->name_length + *out_len <= in_len) { 03554 memcpy(&(in[*out_len]), var->name, 03555 sizeof(oid) * var->name_length); 03556 *out_len += var->name_length; 03557 } else { 03558 return SNMPERR_GENERR; 03559 } 03560 } 03561 03562 DEBUGMSGTL(("build_oid_noalloc", "generated: ")); 03563 DEBUGMSGOID(("build_oid_noalloc", in, *out_len)); 03564 DEBUGMSG(("build_oid_noalloc", "\n")); 03565 return SNMPERR_SUCCESS; 03566 } 03567 03568 int 03569 build_oid(oid ** out, size_t * out_len, 03570 oid * prefix, size_t prefix_len, netsnmp_variable_list * indexes) 03571 { 03572 oid tmpout[MAX_OID_LEN]; 03573 03574 /* 03575 * xxx-rks: inefficent. try only building segments to find index len: 03576 * for (var = indexes; var != NULL; var = var->next_variable) { 03577 * if (build_oid_segment(var) != SNMPERR_SUCCESS) 03578 * return SNMPERR_GENERR; 03579 * *out_len += var->name_length; 03580 * 03581 * then see if it fits in existing buffer, or realloc buffer. 03582 */ 03583 if (build_oid_noalloc(tmpout, sizeof(tmpout), out_len, 03584 prefix, prefix_len, indexes) != SNMPERR_SUCCESS) 03585 return SNMPERR_GENERR; 03586 03588 snmp_clone_mem((void **) out, (void *) tmpout, *out_len * sizeof(oid)); 03589 03590 return SNMPERR_SUCCESS; 03591 } 03592 03593 /* 03594 * vblist_out must contain a pre-allocated string of variables into 03595 * which indexes can be extracted based on the previously existing 03596 * types in the variable chain 03597 * returns: 03598 * SNMPERR_GENERR on error 03599 * SNMPERR_SUCCESS on success 03600 */ 03601 03602 int 03603 parse_oid_indexes(oid * oidIndex, size_t oidLen, 03604 netsnmp_variable_list * data) 03605 { 03606 netsnmp_variable_list *var = data; 03607 03608 while (var && oidLen > 0) { 03609 03610 if (parse_one_oid_index(&oidIndex, &oidLen, var, 0) != 03611 SNMPERR_SUCCESS) 03612 break; 03613 03614 var = var->next_variable; 03615 } 03616 03617 if (var != NULL || oidLen != 0) 03618 return SNMPERR_GENERR; 03619 return SNMPERR_SUCCESS; 03620 } 03621 03622 03623 int 03624 parse_one_oid_index(oid ** oidStart, size_t * oidLen, 03625 netsnmp_variable_list * data, int complete) 03626 { 03627 netsnmp_variable_list *var = data; 03628 oid tmpout[MAX_OID_LEN]; 03629 unsigned int i; 03630 unsigned int uitmp = 0; 03631 03632 oid *oidIndex = *oidStart; 03633 03634 if (var == NULL || ((*oidLen == 0) && (complete == 0))) 03635 return SNMPERR_GENERR; 03636 else { 03637 switch (var->type) { 03638 case ASN_INTEGER: 03639 case ASN_COUNTER: 03640 case ASN_GAUGE: 03641 case ASN_TIMETICKS: 03642 if (*oidLen) { 03643 snmp_set_var_value(var, (u_char *) oidIndex++, 03644 sizeof(long)); 03645 --(*oidLen); 03646 } else { 03647 snmp_set_var_value(var, (u_char *) oidLen, sizeof(long)); 03648 } 03649 DEBUGMSGTL(("parse_oid_indexes", 03650 "Parsed int(%d): %d\n", var->type, 03651 *var->val.integer)); 03652 break; 03653 03654 case ASN_IPADDRESS: 03655 if ((4 > *oidLen) && (complete == 0)) 03656 return SNMPERR_GENERR; 03657 03658 for (i = 0; i < 4 && i < *oidLen; ++i) { 03659 if (oidIndex[i] > 255) { 03660 DEBUGMSGTL(("parse_oid_indexes", 03661 "illegal oid in index: %d\n", oidIndex[0])); 03662 return SNMPERR_GENERR; /* sub-identifier too large */ 03663 } 03664 uitmp = uitmp + (oidIndex[i] << (8*(3-i))); 03665 } 03666 if (4 > (int) (*oidLen)) { 03667 oidIndex += *oidLen; 03668 (*oidLen) = 0; 03669 } else { 03670 oidIndex += 4; 03671 (*oidLen) -= 4; 03672 } 03673 uitmp = htonl(uitmp); /* put it in proper order for byte copies */ 03674 uitmp = 03675 snmp_set_var_value(var, (u_char *) &uitmp, 4); 03676 DEBUGMSGTL(("parse_oid_indexes", 03677 "Parsed ipaddr(%d): %d.%d.%d.%d\n", var->type, 03678 var->val.string[0], var->val.string[1], 03679 var->val.string[2], var->val.string[3])); 03680 break; 03681 03682 case ASN_OBJECT_ID: 03683 case ASN_PRIV_IMPLIED_OBJECT_ID: 03684 if (var->type == ASN_PRIV_IMPLIED_OBJECT_ID) { 03685 /* 03686 * might not be implied, might be fixed len. check if 03687 * caller set up val len, and use it if they did. 03688 */ 03689 if (0 == var->val_len) 03690 uitmp = *oidLen; 03691 else { 03692 DEBUGMSGTL(("parse_oid_indexes:fix", "fixed len oid\n")); 03693 uitmp = var->val_len; 03694 } 03695 } else { 03696 if (*oidLen) { 03697 uitmp = *oidIndex++; 03698 --(*oidLen); 03699 } else { 03700 uitmp = 0; 03701 } 03702 if ((uitmp > *oidLen) && (complete == 0)) 03703 return SNMPERR_GENERR; 03704 } 03705 03706 if (uitmp > MAX_OID_LEN) 03707 return SNMPERR_GENERR; /* too big and illegal */ 03708 03709 if (uitmp > *oidLen) { 03710 memcpy(tmpout, oidIndex, sizeof(oid) * (*oidLen)); 03711 memset(&tmpout[*oidLen], 0x00, 03712 sizeof(oid) * (uitmp - *oidLen)); 03713 snmp_set_var_value(var, (u_char *) tmpout, 03714 sizeof(oid) * uitmp); 03715 oidIndex += *oidLen; 03716 (*oidLen) = 0; 03717 } else { 03718 snmp_set_var_value(var, (u_char *) oidIndex, 03719 sizeof(oid) * uitmp); 03720 oidIndex += uitmp; 03721 (*oidLen) -= uitmp; 03722 } 03723 03724 DEBUGMSGTL(("parse_oid_indexes", "Parsed oid: ")); 03725 DEBUGMSGOID(("parse_oid_indexes", 03726 var->val.objid, var->val_len / sizeof(oid))); 03727 DEBUGMSG(("parse_oid_indexes", "\n")); 03728 break; 03729 03730 case ASN_OPAQUE: 03731 case ASN_OCTET_STR: 03732 case ASN_PRIV_IMPLIED_OCTET_STR: 03733 if (var->type == ASN_PRIV_IMPLIED_OCTET_STR) { 03734 /* 03735 * might not be implied, might be fixed len. check if 03736 * caller set up val len, and use it if they did. 03737 */ 03738 if (0 == var->val_len) 03739 uitmp = *oidLen; 03740 else { 03741 DEBUGMSGTL(("parse_oid_indexes:fix", "fixed len str\n")); 03742 uitmp = var->val_len; 03743 } 03744 } else { 03745 if (*oidLen) { 03746 uitmp = *oidIndex++; 03747 --(*oidLen); 03748 } else { 03749 uitmp = 0; 03750 } 03751 if ((uitmp > *oidLen) && (complete == 0)) 03752 return SNMPERR_GENERR; 03753 } 03754 03755 /* 03756 * we handle this one ourselves since we don't have 03757 * pre-allocated memory to copy from using 03758 * snmp_set_var_value() 03759 */ 03760 03761 if (uitmp == 0) 03762 break; /* zero length strings shouldn't malloc */ 03763 03764 if (uitmp > MAX_OID_LEN) 03765 return SNMPERR_GENERR; /* too big and illegal */ 03766 03767 /* 03768 * malloc by size+1 to allow a null to be appended. 03769 */ 03770 var->val_len = uitmp; 03771 var->val.string = (u_char *) calloc(1, uitmp + 1); 03772 if (var->val.string == NULL) 03773 return SNMPERR_GENERR; 03774 03775 if ((size_t)uitmp > (*oidLen)) { 03776 for (i = 0; i < *oidLen; ++i) 03777 var->val.string[i] = (u_char) * oidIndex++; 03778 for (i = *oidLen; i < uitmp; ++i) 03779 var->val.string[i] = '\0'; 03780 (*oidLen) = 0; 03781 } else { 03782 for (i = 0; i < uitmp; ++i) 03783 var->val.string[i] = (u_char) * oidIndex++; 03784 (*oidLen) -= uitmp; 03785 } 03786 var->val.string[uitmp] = '\0'; 03787 03788 DEBUGMSGTL(("parse_oid_indexes", 03789 "Parsed str(%d): %s\n", var->type, 03790 var->val.string)); 03791 break; 03792 03793 default: 03794 DEBUGMSGTL(("parse_oid_indexes", 03795 "invalid asn type: %d\n", var->type)); 03796 return SNMPERR_GENERR; 03797 } 03798 } 03799 (*oidStart) = oidIndex; 03800 return SNMPERR_SUCCESS; 03801 } 03802 03803 /* 03804 * dump_realloc_oid_to_inetaddress: 03805 * return 0 for failure, 03806 * return 1 for success, 03807 * return 2 for not handled 03808 */ 03809 03810 int 03811 dump_realloc_oid_to_inetaddress(const int addr_type, const oid * objid, size_t objidlen, 03812 u_char ** buf, size_t * buf_len, 03813 size_t * out_len, int allow_realloc, 03814 char quotechar) 03815 { 03816 if (buf) { 03817 int i, len; 03818 char intbuf[64], * p; 03819 unsigned long zone; 03820 03821 memset(intbuf, 0, 64); 03822 03823 p = intbuf; 03824 *p = quotechar; 03825 p++; 03826 switch (addr_type) { 03827 case IPV4: 03828 case IPV4Z: 03829 if ((addr_type == IPV4 && objidlen != 4) || 03830 (addr_type == IPV4Z && objidlen != 8)) 03831 return 2; 03832 03833 len = sprintf(p, "%lu.%lu.%lu.%lu", objid[0], objid[1], objid[2], objid[3]); 03834 p += len; 03835 if (addr_type == IPV4Z) { 03836 zone = ntohl((long)objid[4]); 03837 len = sprintf(p, "%%%lu", zone); 03838 p += len; 03839 } 03840 03841 break; 03842 03843 case IPV6: 03844 case IPV6Z: 03845 if ((addr_type == IPV6 && objidlen != 16) || 03846 (addr_type == IPV6Z && objidlen != 20)) 03847 return 2; 03848 03849 len = 0; 03850 for (i = 0; i < 16; i ++) { 03851 len = snprintf(p, 4, "%02lx:", objid[i]); 03852 p += len; 03853 } 03854 p-- ; /* do not include the last ':' */ 03855 03856 if (addr_type == IPV6Z) { 03857 zone = ntohl((long)objid[16]); 03858 len = sprintf(p, "%%%lu", zone); 03859 p += len; 03860 } 03861 03862 break; 03863 03864 case DNS: 03865 default: 03866 /* DNS can just be handled by dump_realloc_oid_to_string() */ 03867 return 2; 03868 } 03869 03870 *p = quotechar; 03871 03872 return snmp_strcat(buf, buf_len, out_len, allow_realloc, 03873 (const u_char *) intbuf); 03874 } 03875 return 1; 03876 } 03877 03878 int 03879 dump_realloc_oid_to_string(const oid * objid, size_t objidlen, 03880 u_char ** buf, size_t * buf_len, 03881 size_t * out_len, int allow_realloc, 03882 char quotechar) 03883 { 03884 if (buf) { 03885 int i, alen; 03886 03887 for (i = 0, alen = 0; i < (int) objidlen; i++) { 03888 oid tst = objid[i]; 03889 if ((tst > 254) || (!isprint(tst))) { 03890 tst = (oid) '.'; 03891 } 03892 03893 if (alen == 0) { 03894 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) { 03895 while ((*out_len + 2) >= *buf_len) { 03896 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 03897 return 0; 03898 } 03899 } 03900 *(*buf + *out_len) = '\\'; 03901 (*out_len)++; 03902 } 03903 while ((*out_len + 2) >= *buf_len) { 03904 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 03905 return 0; 03906 } 03907 } 03908 *(*buf + *out_len) = quotechar; 03909 (*out_len)++; 03910 } 03911 03912 while ((*out_len + 2) >= *buf_len) { 03913 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 03914 return 0; 03915 } 03916 } 03917 *(*buf + *out_len) = (char) tst; 03918 (*out_len)++; 03919 alen++; 03920 } 03921 03922 if (alen) { 03923 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) { 03924 while ((*out_len + 2) >= *buf_len) { 03925 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 03926 return 0; 03927 } 03928 } 03929 *(*buf + *out_len) = '\\'; 03930 (*out_len)++; 03931 } 03932 while ((*out_len + 2) >= *buf_len) { 03933 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 03934 return 0; 03935 } 03936 } 03937 *(*buf + *out_len) = quotechar; 03938 (*out_len)++; 03939 } 03940 03941 *(*buf + *out_len) = '\0'; 03942 } 03943 03944 return 1; 03945 } 03946 03947 void 03948 _oid_finish_printing(const oid * objid, size_t objidlen, 03949 u_char ** buf, size_t * buf_len, size_t * out_len, 03950 int allow_realloc, int *buf_overflow) { 03951 char intbuf[64]; 03952 if (*buf != NULL && *(*buf + *out_len - 1) != '.') { 03953 if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len, 03954 allow_realloc, 03955 (const u_char *) ".")) { 03956 *buf_overflow = 1; 03957 } 03958 } 03959 03960 while (objidlen-- > 0) { /* output rest of name, uninterpreted */ 03961 sprintf(intbuf, "%lu.", *objid++); 03962 if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len, 03963 allow_realloc, 03964 (const u_char *) intbuf)) { 03965 *buf_overflow = 1; 03966 } 03967 } 03968 03969 if (*buf != NULL) { 03970 *(*buf + *out_len - 1) = '\0'; /* remove trailing dot */ 03971 *out_len = *out_len - 1; 03972 } 03973 } 03974 03975 #ifndef NETSNMP_DISABLE_MIB_LOADING 03976 static struct tree * 03977 _get_realloc_symbol(const oid * objid, size_t objidlen, 03978 struct tree *subtree, 03979 u_char ** buf, size_t * buf_len, size_t * out_len, 03980 int allow_realloc, int *buf_overflow, 03981 struct index_list *in_dices, size_t * end_of_known) 03982 { 03983 struct tree *return_tree = NULL; 03984 int extended_index = 03985 netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_EXTENDED_INDEX); 03986 int output_format = 03987 netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT); 03988 char intbuf[64]; 03989 03990 if (!objid || !buf) { 03991 return NULL; 03992 } 03993 03994 for (; subtree; subtree = subtree->next_peer) { 03995 if (*objid == subtree->subid) { 03996 while (subtree->next_peer && subtree->next_peer->subid == *objid) 03997 subtree = subtree->next_peer; 03998 if (subtree->indexes) { 03999 in_dices = subtree->indexes; 04000 } else if (subtree->augments) { 04001 struct tree *tp2 = 04002 find_tree_node(subtree->augments, -1); 04003 if (tp2) { 04004 in_dices = tp2->indexes; 04005 } 04006 } 04007 04008 if (!strncmp(subtree->label, ANON, ANON_LEN) || 04009 (NETSNMP_OID_OUTPUT_NUMERIC == output_format)) { 04010 sprintf(intbuf, "%lu", subtree->subid); 04011 if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len, 04012 allow_realloc, 04013 (const u_char *) 04014 intbuf)) { 04015 *buf_overflow = 1; 04016 } 04017 } else { 04018 if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len, 04019 allow_realloc, 04020 (const u_char *) 04021 subtree->label)) { 04022 *buf_overflow = 1; 04023 } 04024 } 04025 04026 if (objidlen > 1) { 04027 if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len, 04028 allow_realloc, 04029 (const u_char *) ".")) { 04030 *buf_overflow = 1; 04031 } 04032 04033 return_tree = _get_realloc_symbol(objid + 1, objidlen - 1, 04034 subtree->child_list, 04035 buf, buf_len, out_len, 04036 allow_realloc, 04037 buf_overflow, in_dices, 04038 end_of_known); 04039 } 04040 04041 if (return_tree != NULL) { 04042 return return_tree; 04043 } else { 04044 return subtree; 04045 } 04046 } 04047 } 04048 04049 04050 if (end_of_known) { 04051 *end_of_known = *out_len; 04052 } 04053 04054 /* 04055 * Subtree not found. 04056 */ 04057 04058 while (in_dices && (objidlen > 0) && 04059 (NETSNMP_OID_OUTPUT_NUMERIC != output_format) && 04060 !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS)) { 04061 size_t numids; 04062 struct tree *tp; 04063 04064 tp = find_tree_node(in_dices->ilabel, -1); 04065 04066 if (!tp) { 04067 /* 04068 * Can't find an index in the mib tree. Bail. 04069 */ 04070 goto finish_it; 04071 } 04072 04073 if (extended_index) { 04074 if (*buf != NULL && *(*buf + *out_len - 1) == '.') { 04075 (*out_len)--; 04076 } 04077 if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len, 04078 allow_realloc, 04079 (const u_char *) "[")) { 04080 *buf_overflow = 1; 04081 } 04082 } 04083 04084 switch (tp->type) { 04085 case TYPE_OCTETSTR: 04086 if (extended_index && tp->hint) { 04087 netsnmp_variable_list var; 04088 u_char buffer[1024]; 04089 int i; 04090 04091 memset(&var, 0, sizeof var); 04092 if (in_dices->isimplied) { 04093 numids = objidlen; 04094 if (numids > objidlen) 04095 goto finish_it; 04096 } else if (tp->ranges && !tp->ranges->next 04097 && tp->ranges->low == tp->ranges->high) { 04098 numids = tp->ranges->low; 04099 if (numids > objidlen) 04100 goto finish_it; 04101 } else { 04102 numids = *objid; 04103 if (numids >= objidlen) 04104 goto finish_it; 04105 objid++; 04106 objidlen--; 04107 } 04108 if (numids > objidlen) 04109 goto finish_it; 04110 for (i = 0; i < (int) numids; i++) 04111 buffer[i] = (u_char) objid[i]; 04112 var.type = ASN_OCTET_STR; 04113 var.val.string = buffer; 04114 var.val_len = numids; 04115 if (!*buf_overflow) { 04116 if (!sprint_realloc_octet_string(buf, buf_len, out_len, 04117 allow_realloc, &var, 04118 NULL, tp->hint, 04119 NULL)) { 04120 *buf_overflow = 1; 04121 } 04122 } 04123 } else if (in_dices->isimplied) { 04124 numids = objidlen; 04125 if (numids > objidlen) 04126 goto finish_it; 04127 04128 if (!*buf_overflow) { 04129 if (!dump_realloc_oid_to_string 04130 (objid, numids, buf, buf_len, out_len, 04131 allow_realloc, '\'')) { 04132 *buf_overflow = 1; 04133 } 04134 } 04135 } else if (tp->ranges && !tp->ranges->next 04136 && tp->ranges->low == tp->ranges->high) { 04137 /* 04138 * a fixed-length octet string 04139 */ 04140 numids = tp->ranges->low; 04141 if (numids > objidlen) 04142 goto finish_it; 04143 04144 if (!*buf_overflow) { 04145 if (!dump_realloc_oid_to_string 04146 (objid, numids, buf, buf_len, out_len, 04147 allow_realloc, '\'')) { 04148 *buf_overflow = 1; 04149 } 04150 } 04151 } else { 04152 numids = (size_t) * objid + 1; 04153 if (numids > objidlen) 04154 goto finish_it; 04155 if (numids == 1) { 04156 if (netsnmp_ds_get_boolean 04157 (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) { 04158 if (!*buf_overflow 04159 && !snmp_strcat(buf, buf_len, out_len, 04160 allow_realloc, 04161 (const u_char *) "\\")) { 04162 *buf_overflow = 1; 04163 } 04164 } 04165 if (!*buf_overflow 04166 && !snmp_strcat(buf, buf_len, out_len, 04167 allow_realloc, 04168 (const u_char *) "\"")) { 04169 *buf_overflow = 1; 04170 } 04171 if (netsnmp_ds_get_boolean 04172 (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ESCAPE_QUOTES)) { 04173 if (!*buf_overflow 04174 && !snmp_strcat(buf, buf_len, out_len, 04175 allow_realloc, 04176 (const u_char *) "\\")) { 04177 *buf_overflow = 1; 04178 } 04179 } 04180 if (!*buf_overflow 04181 && !snmp_strcat(buf, buf_len, out_len, 04182 allow_realloc, 04183 (const u_char *) "\"")) { 04184 *buf_overflow = 1; 04185 } 04186 } else { 04187 if (!*buf_overflow) { 04188 struct tree * next_peer; 04189 int normal_handling = 1; 04190 04191 if (tp->next_peer) { 04192 next_peer = tp->next_peer; 04193 } 04194 04195 /* Try handling the InetAddress in the OID, in case of failure, 04196 * use the normal_handling. 04197 */ 04198 if (tp->next_peer && 04199 tp->tc_index != -1 && 04200 next_peer->tc_index != -1 && 04201 strcmp(get_tc_descriptor(tp->tc_index), "InetAddress") == 0 && 04202 strcmp(get_tc_descriptor(next_peer->tc_index), 04203 "InetAddressType") == 0 ) { 04204 04205 int ret; 04206 int addr_type = *(objid - 1); 04207 04208 ret = dump_realloc_oid_to_inetaddress(addr_type, 04209 objid + 1, numids - 1, buf, buf_len, out_len, 04210 allow_realloc, '"'); 04211 if (ret != 2) { 04212 normal_handling = 0; 04213 if (ret == 0) { 04214 *buf_overflow = 1; 04215 } 04216 04217 } 04218 } 04219 if (normal_handling && !dump_realloc_oid_to_string 04220 (objid + 1, numids - 1, buf, buf_len, out_len, 04221 allow_realloc, '"')) { 04222 *buf_overflow = 1; 04223 } 04224 } 04225 } 04226 } 04227 objid += numids; 04228 objidlen -= numids; 04229 break; 04230 04231 case TYPE_INTEGER32: 04232 case TYPE_UINTEGER: 04233 case TYPE_UNSIGNED32: 04234 case TYPE_GAUGE: 04235 case TYPE_INTEGER: 04236 if (tp->enums) { 04237 struct enum_list *ep = tp->enums; 04238 while (ep && ep->value != (int) (*objid)) { 04239 ep = ep->next; 04240 } 04241 if (ep) { 04242 if (!*buf_overflow 04243 && !snmp_strcat(buf, buf_len, out_len, 04244 allow_realloc, 04245 (const u_char *) ep->label)) { 04246 *buf_overflow = 1; 04247 } 04248 } else { 04249 sprintf(intbuf, "%lu", *objid); 04250 if (!*buf_overflow 04251 && !snmp_strcat(buf, buf_len, out_len, 04252 allow_realloc, 04253 (const u_char *) intbuf)) { 04254 *buf_overflow = 1; 04255 } 04256 } 04257 } else { 04258 sprintf(intbuf, "%lu", *objid); 04259 if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len, 04260 allow_realloc, 04261 (const u_char *) 04262 intbuf)) { 04263 *buf_overflow = 1; 04264 } 04265 } 04266 objid++; 04267 objidlen--; 04268 break; 04269 04270 case TYPE_OBJID: 04271 if (in_dices->isimplied) { 04272 numids = objidlen; 04273 } else { 04274 numids = (size_t) * objid + 1; 04275 } 04276 if (numids > objidlen) 04277 goto finish_it; 04278 if (extended_index) { 04279 if (in_dices->isimplied) { 04280 if (!*buf_overflow 04281 && !netsnmp_sprint_realloc_objid_tree(buf, buf_len, 04282 out_len, 04283 allow_realloc, 04284 buf_overflow, 04285 objid, 04286 numids)) { 04287 *buf_overflow = 1; 04288 } 04289 } else { 04290 if (!*buf_overflow 04291 && !netsnmp_sprint_realloc_objid_tree(buf, buf_len, 04292 out_len, 04293 allow_realloc, 04294 buf_overflow, 04295 objid + 1, 04296 numids - 04297 1)) { 04298 *buf_overflow = 1; 04299 } 04300 } 04301 } else { 04302 _get_realloc_symbol(objid, numids, NULL, buf, buf_len, 04303 out_len, allow_realloc, buf_overflow, 04304 NULL, NULL); 04305 } 04306 objid += (numids); 04307 objidlen -= (numids); 04308 break; 04309 04310 case TYPE_IPADDR: 04311 if (objidlen < 4) 04312 goto finish_it; 04313 sprintf(intbuf, "%lu.%lu.%lu.%lu", 04314 objid[0], objid[1], objid[2], objid[3]); 04315 objid += 4; 04316 objidlen -= 4; 04317 if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len, 04318 allow_realloc, 04319 (const u_char *) intbuf)) { 04320 *buf_overflow = 1; 04321 } 04322 break; 04323 04324 case TYPE_NETADDR:{ 04325 oid ntype = *objid++; 04326 04327 objidlen--; 04328 sprintf(intbuf, "%lu.", ntype); 04329 if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len, 04330 allow_realloc, 04331 (const u_char *) 04332 intbuf)) { 04333 *buf_overflow = 1; 04334 } 04335 04336 if (ntype == 1 && objidlen >= 4) { 04337 sprintf(intbuf, "%lu.%lu.%lu.%lu", 04338 objid[0], objid[1], objid[2], objid[3]); 04339 if (!*buf_overflow 04340 && !snmp_strcat(buf, buf_len, out_len, 04341 allow_realloc, 04342 (const u_char *) intbuf)) { 04343 *buf_overflow = 1; 04344 } 04345 objid += 4; 04346 objidlen -= 4; 04347 } else { 04348 goto finish_it; 04349 } 04350 } 04351 break; 04352 04353 case TYPE_NSAPADDRESS: 04354 default: 04355 goto finish_it; 04356 break; 04357 } 04358 04359 if (extended_index) { 04360 if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len, 04361 allow_realloc, 04362 (const u_char *) "]")) { 04363 *buf_overflow = 1; 04364 } 04365 } else { 04366 if (!*buf_overflow && !snmp_strcat(buf, buf_len, out_len, 04367 allow_realloc, 04368 (const u_char *) ".")) { 04369 *buf_overflow = 1; 04370 } 04371 } 04372 in_dices = in_dices->next; 04373 } 04374 04375 finish_it: 04376 _oid_finish_printing(objid, objidlen, 04377 buf, buf_len, out_len, 04378 allow_realloc, buf_overflow); 04379 return NULL; 04380 } 04381 04382 struct tree * 04383 get_tree(const oid * objid, size_t objidlen, struct tree *subtree) 04384 { 04385 struct tree *return_tree = NULL; 04386 04387 for (; subtree; subtree = subtree->next_peer) { 04388 if (*objid == subtree->subid) 04389 goto found; 04390 } 04391 04392 return NULL; 04393 04394 found: 04395 while (subtree->next_peer && subtree->next_peer->subid == *objid) 04396 subtree = subtree->next_peer; 04397 if (objidlen > 1) 04398 return_tree = 04399 get_tree(objid + 1, objidlen - 1, subtree->child_list); 04400 if (return_tree != NULL) 04401 return return_tree; 04402 else 04403 return subtree; 04404 } 04405 04411 void 04412 print_description(oid * objid, size_t objidlen, /* number of subidentifiers */ 04413 int width) 04414 { 04415 fprint_description(stdout, objid, objidlen, width); 04416 } 04417 04418 04427 void 04428 fprint_description(FILE * f, oid * objid, size_t objidlen, 04429 int width) 04430 { 04431 u_char *buf = NULL; 04432 size_t buf_len = 256, out_len = 0; 04433 04434 if ((buf = (u_char *) calloc(buf_len, 1)) == NULL) { 04435 fprintf(f, "[TRUNCATED]\n"); 04436 return; 04437 } else { 04438 if (!sprint_realloc_description(&buf, &buf_len, &out_len, 1, 04439 objid, objidlen, width)) { 04440 fprintf(f, "%s [TRUNCATED]\n", buf); 04441 } else { 04442 fprintf(f, "%s\n", buf); 04443 } 04444 } 04445 04446 SNMP_FREE(buf); 04447 } 04448 04449 int 04450 snprint_description(char *buf, size_t buf_len, 04451 oid * objid, size_t objidlen, int width) 04452 { 04453 size_t out_len = 0; 04454 04455 if (sprint_realloc_description((u_char **) & buf, &buf_len, &out_len, 0, 04456 objid, objidlen, width)) { 04457 return (int) out_len; 04458 } else { 04459 return -1; 04460 } 04461 } 04462 04463 int 04464 sprint_realloc_description(u_char ** buf, size_t * buf_len, 04465 size_t * out_len, int allow_realloc, 04466 oid * objid, size_t objidlen, int width) 04467 { 04468 struct tree *tp = get_tree(objid, objidlen, tree_head); 04469 struct tree *subtree = tree_head; 04470 int pos, len; 04471 char tmpbuf[128]; 04472 const char *cp; 04473 04474 if (NULL == tp) 04475 return 0; 04476 04477 if (tp->type <= TYPE_SIMPLE_LAST) 04478 cp = " OBJECT-TYPE"; 04479 else 04480 switch (tp->type) { 04481 case TYPE_TRAPTYPE: 04482 cp = " TRAP-TYPE"; 04483 break; 04484 case TYPE_NOTIFTYPE: 04485 cp = " NOTIFICATION-TYPE"; 04486 break; 04487 case TYPE_OBJGROUP: 04488 cp = " OBJECT-GROUP"; 04489 break; 04490 case TYPE_AGENTCAP: 04491 cp = " AGENT-CAPABILITIES"; 04492 break; 04493 case TYPE_MODID: 04494 cp = " MODULE-IDENTITY"; 04495 break; 04496 case TYPE_OBJIDENTITY: 04497 cp = " OBJECT-IDENTITY"; 04498 break; 04499 case TYPE_MODCOMP: 04500 cp = " MODULE-COMPLIANCE"; 04501 break; 04502 default: 04503 sprintf(tmpbuf, " type_%d", tp->type); 04504 cp = tmpbuf; 04505 } 04506 04507 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->label) || 04508 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, cp) || 04509 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n")) { 04510 return 0; 04511 } 04512 if (!print_tree_node(buf, buf_len, out_len, allow_realloc, tp, width)) 04513 return 0; 04514 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "::= {")) 04515 return 0; 04516 pos = 5; 04517 while (objidlen > 1) { 04518 for (; subtree; subtree = subtree->next_peer) { 04519 if (*objid == subtree->subid) { 04520 while (subtree->next_peer && subtree->next_peer->subid == *objid) 04521 subtree = subtree->next_peer; 04522 if (strncmp(subtree->label, ANON, ANON_LEN)) { 04523 snprintf(tmpbuf, sizeof(tmpbuf), " %s(%lu)", subtree->label, subtree->subid); 04524 tmpbuf[ sizeof(tmpbuf)-1 ] = 0; 04525 } else 04526 sprintf(tmpbuf, " %lu", subtree->subid); 04527 len = strlen(tmpbuf); 04528 if (pos + len + 2 > width) { 04529 if (!snmp_cstrcat(buf, buf_len, out_len, 04530 allow_realloc, "\n ")) 04531 return 0; 04532 pos = 5; 04533 } 04534 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tmpbuf)) 04535 return 0; 04536 pos += len; 04537 objid++; 04538 objidlen--; 04539 break; 04540 } 04541 } 04542 if (subtree) 04543 subtree = subtree->child_list; 04544 else 04545 break; 04546 } 04547 while (objidlen > 1) { 04548 sprintf(tmpbuf, " %lu", *objid); 04549 len = strlen(tmpbuf); 04550 if (pos + len + 2 > width) { 04551 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n ")) 04552 return 0; 04553 pos = 5; 04554 } 04555 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tmpbuf)) 04556 return 0; 04557 pos += len; 04558 objid++; 04559 objidlen--; 04560 } 04561 sprintf(tmpbuf, " %lu }", *objid); 04562 len = strlen(tmpbuf); 04563 if (pos + len + 2 > width) { 04564 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n ")) 04565 return 0; 04566 pos = 5; 04567 } 04568 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tmpbuf)) 04569 return 0; 04570 return 1; 04571 } 04572 04573 static int 04574 print_tree_node(u_char ** buf, size_t * buf_len, 04575 size_t * out_len, int allow_realloc, 04576 struct tree *tp, int width) 04577 { 04578 const char *cp; 04579 char str[MAXTOKEN]; 04580 int i, prevmod, pos, len; 04581 04582 if (tp) { 04583 module_name(tp->modid, str); 04584 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " -- FROM\t") || 04585 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str)) 04586 return 0; 04587 pos = 16+strlen(str); 04588 for (i = 1, prevmod = tp->modid; i < tp->number_modules; i++) { 04589 if (prevmod != tp->module_list[i]) { 04590 module_name(tp->module_list[i], str); 04591 len = strlen(str); 04592 if (pos + len + 2 > width) { 04593 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04594 ",\n --\t\t")) 04595 return 0; 04596 pos = 16; 04597 } 04598 else { 04599 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", ")) 04600 return 0; 04601 pos += 2; 04602 } 04603 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str)) 04604 return 0; 04605 pos += len; 04606 } 04607 prevmod = tp->module_list[i]; 04608 } 04609 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n")) 04610 return 0; 04611 if (tp->tc_index != -1) { 04612 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04613 " -- TEXTUAL CONVENTION ") || 04614 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04615 get_tc_descriptor(tp->tc_index)) || 04616 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n")) 04617 return 0; 04618 } 04619 switch (tp->type) { 04620 case TYPE_OBJID: 04621 cp = "OBJECT IDENTIFIER"; 04622 break; 04623 case TYPE_OCTETSTR: 04624 cp = "OCTET STRING"; 04625 break; 04626 case TYPE_INTEGER: 04627 cp = "INTEGER"; 04628 break; 04629 case TYPE_NETADDR: 04630 cp = "NetworkAddress"; 04631 break; 04632 case TYPE_IPADDR: 04633 cp = "IpAddress"; 04634 break; 04635 case TYPE_COUNTER: 04636 cp = "Counter32"; 04637 break; 04638 case TYPE_GAUGE: 04639 cp = "Gauge32"; 04640 break; 04641 case TYPE_TIMETICKS: 04642 cp = "TimeTicks"; 04643 break; 04644 case TYPE_OPAQUE: 04645 cp = "Opaque"; 04646 break; 04647 case TYPE_NULL: 04648 cp = "NULL"; 04649 break; 04650 case TYPE_COUNTER64: 04651 cp = "Counter64"; 04652 break; 04653 case TYPE_BITSTRING: 04654 cp = "BITS"; 04655 break; 04656 case TYPE_NSAPADDRESS: 04657 cp = "NsapAddress"; 04658 break; 04659 case TYPE_UINTEGER: 04660 cp = "UInteger32"; 04661 break; 04662 case TYPE_UNSIGNED32: 04663 cp = "Unsigned32"; 04664 break; 04665 case TYPE_INTEGER32: 04666 cp = "Integer32"; 04667 break; 04668 default: 04669 cp = NULL; 04670 break; 04671 } 04672 #if NETSNMP_ENABLE_TESTING_CODE 04673 if (!cp && (tp->ranges || tp->enums)) { /* ranges without type ? */ 04674 sprintf(str, "?0 with %s %s ?", 04675 tp->ranges ? "Range" : "", tp->enums ? "Enum" : ""); 04676 cp = str; 04677 } 04678 #endif /* NETSNMP_ENABLE_TESTING_CODE */ 04679 if (cp) 04680 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04681 " SYNTAX\t") || 04682 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, cp)) 04683 return 0; 04684 if (tp->ranges) { 04685 struct range_list *rp = tp->ranges; 04686 int first = 1; 04687 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " (")) 04688 return 0; 04689 while (rp) { 04690 if (rp->low == rp->high) 04691 sprintf(str, "%s%d", (first ? "" : " | "), rp->low ); 04692 else 04693 sprintf(str, "%s%d..%d", (first ? "" : " | "), 04694 rp->low, rp->high); 04695 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str)) 04696 return 0; 04697 if (first) 04698 first = 0; 04699 rp = rp->next; 04700 } 04701 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ") ")) 04702 return 0; 04703 } 04704 if (tp->enums) { 04705 struct enum_list *ep = tp->enums; 04706 int first = 1; 04707 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " {")) 04708 return 0; 04709 pos = 16 + strlen(cp) + 2; 04710 while (ep) { 04711 if (first) 04712 first = 0; 04713 else 04714 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", ")) 04715 return 0; 04716 snprintf(str, sizeof(str), "%s(%d)", ep->label, ep->value); 04717 str[ sizeof(str)-1 ] = 0; 04718 len = strlen(str); 04719 if (pos + len + 2 > width) { 04720 if (!snmp_cstrcat(buf, buf_len, out_len, 04721 allow_realloc, "\n\t\t ")) 04722 return 0; 04723 pos = 18; 04724 } 04725 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str)) 04726 return 0; 04727 pos += len + 2; 04728 ep = ep->next; 04729 } 04730 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "} ")) 04731 return 0; 04732 } 04733 if (cp) 04734 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n")) 04735 return 0; 04736 if (tp->hint) 04737 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04738 " DISPLAY-HINT\t\"") || 04739 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->hint) || 04740 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\n")) 04741 return 0; 04742 if (tp->units) 04743 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04744 " UNITS\t\t\"") || 04745 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->units) || 04746 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\n")) 04747 return 0; 04748 switch (tp->access) { 04749 case MIB_ACCESS_READONLY: 04750 cp = "read-only"; 04751 break; 04752 case MIB_ACCESS_READWRITE: 04753 cp = "read-write"; 04754 break; 04755 case MIB_ACCESS_WRITEONLY: 04756 cp = "write-only"; 04757 break; 04758 case MIB_ACCESS_NOACCESS: 04759 cp = "not-accessible"; 04760 break; 04761 case MIB_ACCESS_NOTIFY: 04762 cp = "accessible-for-notify"; 04763 break; 04764 case MIB_ACCESS_CREATE: 04765 cp = "read-create"; 04766 break; 04767 case 0: 04768 cp = NULL; 04769 break; 04770 default: 04771 sprintf(str, "access_%d", tp->access); 04772 cp = str; 04773 } 04774 if (cp) 04775 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04776 " MAX-ACCESS\t") || 04777 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, cp) || 04778 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n")) 04779 return 0; 04780 switch (tp->status) { 04781 case MIB_STATUS_MANDATORY: 04782 cp = "mandatory"; 04783 break; 04784 case MIB_STATUS_OPTIONAL: 04785 cp = "optional"; 04786 break; 04787 case MIB_STATUS_OBSOLETE: 04788 cp = "obsolete"; 04789 break; 04790 case MIB_STATUS_DEPRECATED: 04791 cp = "deprecated"; 04792 break; 04793 case MIB_STATUS_CURRENT: 04794 cp = "current"; 04795 break; 04796 case 0: 04797 cp = NULL; 04798 break; 04799 default: 04800 sprintf(str, "status_%d", tp->status); 04801 cp = str; 04802 } 04803 #if NETSNMP_ENABLE_TESTING_CODE 04804 if (!cp && (tp->indexes)) { /* index without status ? */ 04805 sprintf(str, "?0 with %s ?", tp->indexes ? "Index" : ""); 04806 cp = str; 04807 } 04808 #endif /* NETSNMP_ENABLE_TESTING_CODE */ 04809 if (cp) 04810 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04811 " STATUS\t") || 04812 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, cp) || 04813 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n")) 04814 return 0; 04815 if (tp->augments) 04816 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04817 " AUGMENTS\t{ ") || 04818 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->augments) || 04819 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n")) 04820 return 0; 04821 if (tp->indexes) { 04822 struct index_list *ip = tp->indexes; 04823 int first = 1; 04824 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04825 " INDEX\t\t{ ")) 04826 return 0; 04827 pos = 16 + 2; 04828 while (ip) { 04829 if (first) 04830 first = 0; 04831 else 04832 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", ")) 04833 return 0; 04834 snprintf(str, sizeof(str), "%s%s", 04835 ip->isimplied ? "IMPLIED " : "", 04836 ip->ilabel); 04837 str[ sizeof(str)-1 ] = 0; 04838 len = strlen(str); 04839 if (pos + len + 2 > width) { 04840 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\n\t\t ")) 04841 return 0; 04842 pos = 16 + 2; 04843 } 04844 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str)) 04845 return 0; 04846 pos += len + 2; 04847 ip = ip->next; 04848 } 04849 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n")) 04850 return 0; 04851 } 04852 if (tp->varbinds) { 04853 struct varbind_list *vp = tp->varbinds; 04854 int first = 1; 04855 04856 if (tp->type == TYPE_TRAPTYPE) { 04857 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04858 " VARIABLES\t{ ")) 04859 return 0; 04860 } else { 04861 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04862 " OBJECTS\t{ ")) 04863 return 0; 04864 } 04865 pos = 16 + 2; 04866 while (vp) { 04867 if (first) 04868 first = 0; 04869 else 04870 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, ", ")) 04871 return 0; 04872 snprintf(str, sizeof(str), "%s", vp->vblabel); 04873 str[ sizeof(str)-1 ] = 0; 04874 len = strlen(str); 04875 if (pos + len + 2 > width) { 04876 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04877 "\n\t\t ")) 04878 return 0; 04879 pos = 16 + 2; 04880 } 04881 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, str)) 04882 return 0; 04883 pos += len + 2; 04884 vp = vp->next; 04885 } 04886 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n")) 04887 return 0; 04888 } 04889 if (tp->description) 04890 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04891 " DESCRIPTION\t\"") || 04892 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->description) || 04893 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "\"\n")) 04894 return 0; 04895 if (tp->defaultValue) 04896 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, 04897 " DEFVAL\t{ ") || 04898 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tp->defaultValue) || 04899 !snmp_cstrcat(buf, buf_len, out_len, allow_realloc, " }\n")) 04900 return 0; 04901 } else 04902 if (!snmp_cstrcat(buf, buf_len, out_len, allow_realloc, "No description\n")) 04903 return 0; 04904 return 1; 04905 } 04906 04907 int 04908 get_module_node(const char *fname, 04909 const char *module, oid * objid, size_t * objidlen) 04910 { 04911 int modid, rc = 0; 04912 struct tree *tp; 04913 char *name, *cp; 04914 04915 if (!strcmp(module, "ANY")) 04916 modid = -1; 04917 else { 04918 netsnmp_read_module(module); 04919 modid = which_module(module); 04920 if (modid == -1) 04921 return 0; 04922 } 04923 04924 /* 04925 * Isolate the first component of the name ... 04926 */ 04927 name = strdup(fname); 04928 cp = strchr(name, '.'); 04929 if (cp != NULL) { 04930 *cp = '\0'; 04931 cp++; 04932 } 04933 /* 04934 * ... and locate it in the tree. 04935 */ 04936 tp = find_tree_node(name, modid); 04937 if (tp) { 04938 size_t maxlen = *objidlen; 04939 04940 /* 04941 * Set the first element of the object ID 04942 */ 04943 if (node_to_oid(tp, objid, objidlen)) { 04944 rc = 1; 04945 04946 /* 04947 * If the name requested was more than one element, 04948 * tag on the rest of the components 04949 */ 04950 if (cp != NULL) 04951 rc = _add_strings_to_oid(tp, cp, objid, objidlen, maxlen); 04952 } 04953 } 04954 04955 SNMP_FREE(name); 04956 return (rc); 04957 } 04958 04959 04977 static int 04978 node_to_oid(struct tree *tp, oid * objid, size_t * objidlen) 04979 { 04980 int numids, lenids; 04981 oid *op; 04982 04983 if (!tp || !objid || !objidlen) 04984 return 0; 04985 04986 lenids = (int) *objidlen; 04987 op = objid + lenids; /* points after the last element */ 04988 04989 for (numids = 0; tp; tp = tp->parent, numids++) { 04990 if (numids >= lenids) 04991 continue; 04992 --op; 04993 *op = tp->subid; 04994 } 04995 04996 *objidlen = (size_t) numids; 04997 if (numids > lenids) { 04998 return 0; 04999 } 05000 05001 if (numids < lenids) 05002 memmove(objid, op, numids * sizeof(oid)); 05003 05004 return (numids); 05005 } 05006 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 05007 05008 /* 05009 * Replace \x with x stop at eos_marker 05010 * return NULL if eos_marker not found 05011 */ 05012 static char *_apply_escapes(char *src, char eos_marker) 05013 { 05014 char *dst; 05015 int backslash = 0; 05016 05017 dst = src; 05018 while (*src) { 05019 if (backslash) { 05020 backslash = 0; 05021 *dst++ = *src; 05022 } else { 05023 if (eos_marker == *src) break; 05024 if ('\\' == *src) { 05025 backslash = 1; 05026 } else { 05027 *dst++ = *src; 05028 } 05029 } 05030 src++; 05031 } 05032 if (!*src) { 05033 /* never found eos_marker */ 05034 return NULL; 05035 } else { 05036 *dst = 0; 05037 return src; 05038 } 05039 } 05040 05041 static int 05042 #ifndef NETSNMP_DISABLE_MIB_LOADING 05043 _add_strings_to_oid(struct tree *tp, char *cp, 05044 oid * objid, size_t * objidlen, size_t maxlen) 05045 #else 05046 _add_strings_to_oid(void *tp, char *cp, 05047 oid * objid, size_t * objidlen, size_t maxlen) 05048 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 05049 { 05050 oid subid; 05051 int len_index = 1000000; 05052 #ifndef NETSNMP_DISABLE_MIB_LOADING 05053 struct tree *tp2 = NULL; 05054 struct index_list *in_dices = NULL; 05055 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 05056 char *fcp, *ecp, *cp2 = NULL; 05057 char doingquote; 05058 int len = -1, pos = -1; 05059 #ifndef NETSNMP_DISABLE_MIB_LOADING 05060 int check = 05061 !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE); 05062 int do_hint = !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NO_DISPLAY_HINT); 05063 05064 while (cp && tp && tp->child_list) { 05065 fcp = cp; 05066 tp2 = tp->child_list; 05067 /* 05068 * Isolate the next entry 05069 */ 05070 cp2 = strchr(cp, '.'); 05071 if (cp2) 05072 *cp2++ = '\0'; 05073 05074 /* 05075 * Search for the appropriate child 05076 */ 05077 if (isdigit(*cp)) { 05078 subid = strtoul(cp, &ecp, 0); 05079 if (*ecp) 05080 goto bad_id; 05081 while (tp2 && tp2->subid != subid) 05082 tp2 = tp2->next_peer; 05083 } else { 05084 while (tp2 && strcmp(tp2->label, fcp)) 05085 tp2 = tp2->next_peer; 05086 if (!tp2) 05087 goto bad_id; 05088 subid = tp2->subid; 05089 } 05090 if (*objidlen >= maxlen) 05091 goto bad_id; 05092 while (tp2 && tp2->next_peer && tp2->next_peer->subid == subid) 05093 tp2 = tp2->next_peer; 05094 objid[*objidlen] = subid; 05095 (*objidlen)++; 05096 05097 cp = cp2; 05098 if (!tp2) 05099 break; 05100 tp = tp2; 05101 } 05102 05103 if (tp && !tp->child_list) { 05104 if ((tp2 = tp->parent)) { 05105 if (tp2->indexes) 05106 in_dices = tp2->indexes; 05107 else if (tp2->augments) { 05108 tp2 = find_tree_node(tp2->augments, -1); 05109 if (tp2) 05110 in_dices = tp2->indexes; 05111 } 05112 } 05113 tp = NULL; 05114 } 05115 05116 while (cp && in_dices) { 05117 fcp = cp; 05118 05119 tp = find_tree_node(in_dices->ilabel, -1); 05120 if (!tp) 05121 break; 05122 switch (tp->type) { 05123 case TYPE_INTEGER: 05124 case TYPE_INTEGER32: 05125 case TYPE_UINTEGER: 05126 case TYPE_UNSIGNED32: 05127 case TYPE_TIMETICKS: 05128 /* 05129 * Isolate the next entry 05130 */ 05131 cp2 = strchr(cp, '.'); 05132 if (cp2) 05133 *cp2++ = '\0'; 05134 if (isdigit(*cp)) { 05135 subid = strtoul(cp, &ecp, 0); 05136 if (*ecp) 05137 goto bad_id; 05138 } else { 05139 if (tp->enums) { 05140 struct enum_list *ep = tp->enums; 05141 while (ep && strcmp(ep->label, cp)) 05142 ep = ep->next; 05143 if (!ep) 05144 goto bad_id; 05145 subid = ep->value; 05146 } else 05147 goto bad_id; 05148 } 05149 if (check && tp->ranges) { 05150 struct range_list *rp = tp->ranges; 05151 int ok = 0; 05152 if (tp->type == TYPE_INTEGER || 05153 tp->type == TYPE_INTEGER32) { 05154 while (!ok && rp) { 05155 if ((rp->low <= (int) subid) 05156 && ((int) subid <= rp->high)) 05157 ok = 1; 05158 else 05159 rp = rp->next; 05160 } 05161 } else { /* check unsigned range */ 05162 while (!ok && rp) { 05163 if (((unsigned int)rp->low <= subid) 05164 && (subid <= (unsigned int)rp->high)) 05165 ok = 1; 05166 else 05167 rp = rp->next; 05168 } 05169 } 05170 if (!ok) 05171 goto bad_id; 05172 } 05173 if (*objidlen >= maxlen) 05174 goto bad_id; 05175 objid[*objidlen] = subid; 05176 (*objidlen)++; 05177 break; 05178 case TYPE_IPADDR: 05179 if (*objidlen + 4 > maxlen) 05180 goto bad_id; 05181 for (subid = 0; cp && subid < 4; subid++) { 05182 fcp = cp; 05183 cp2 = strchr(cp, '.'); 05184 if (cp2) 05185 *cp2++ = 0; 05186 objid[*objidlen] = strtoul(cp, &ecp, 0); 05187 if (*ecp) 05188 goto bad_id; 05189 if (check && objid[*objidlen] > 255) 05190 goto bad_id; 05191 (*objidlen)++; 05192 cp = cp2; 05193 } 05194 break; 05195 case TYPE_OCTETSTR: 05196 if (tp->ranges && !tp->ranges->next 05197 && tp->ranges->low == tp->ranges->high) 05198 len = tp->ranges->low; 05199 else 05200 len = -1; 05201 pos = 0; 05202 if (*cp == '"' || *cp == '\'') { 05203 doingquote = *cp++; 05204 /* 05205 * insert length if requested 05206 */ 05207 if (!in_dices->isimplied && len == -1) { 05208 if (doingquote == '\'') { 05209 snmp_set_detail 05210 ("'-quote is for fixed length strings"); 05211 return 0; 05212 } 05213 if (*objidlen >= maxlen) 05214 goto bad_id; 05215 len_index = *objidlen; 05216 (*objidlen)++; 05217 } else if (doingquote == '"') { 05218 snmp_set_detail 05219 ("\"-quote is for variable length strings"); 05220 return 0; 05221 } 05222 05223 cp2 = _apply_escapes(cp, doingquote); 05224 if (!cp2) goto bad_id; 05225 else { 05226 unsigned char *new_val; 05227 int new_val_len; 05228 int parsed_hint = 0; 05229 const char *parsed_value; 05230 05231 if (do_hint && tp->hint) { 05232 parsed_value = parse_octet_hint(tp->hint, cp, 05233 &new_val, &new_val_len); 05234 parsed_hint = parsed_value == NULL; 05235 } 05236 if (parsed_hint) { 05237 int i; 05238 for (i = 0; i < new_val_len; i++) { 05239 if (*objidlen >= maxlen) goto bad_id; 05240 objid[ *objidlen ] = new_val[i]; 05241 (*objidlen)++; 05242 pos++; 05243 } 05244 SNMP_FREE(new_val); 05245 } else { 05246 while(*cp) { 05247 if (*objidlen >= maxlen) goto bad_id; 05248 objid[ *objidlen ] = *cp++; 05249 (*objidlen)++; 05250 pos++; 05251 } 05252 } 05253 } 05254 05255 cp2++; 05256 if (!*cp2) 05257 cp2 = NULL; 05258 else if (*cp2 != '.') 05259 goto bad_id; 05260 else 05261 cp2++; 05262 if (check) { 05263 if (len == -1) { 05264 struct range_list *rp = tp->ranges; 05265 int ok = 0; 05266 while (rp && !ok) 05267 if (rp->low <= pos && pos <= rp->high) 05268 ok = 1; 05269 else 05270 rp = rp->next; 05271 if (!ok) 05272 goto bad_id; 05273 if (!in_dices->isimplied) 05274 objid[len_index] = pos; 05275 } else if (pos != len) 05276 goto bad_id; 05277 } 05278 else if (len == -1 && !in_dices->isimplied) 05279 objid[len_index] = pos; 05280 } else { 05281 if (!in_dices->isimplied && len == -1) { 05282 fcp = cp; 05283 cp2 = strchr(cp, '.'); 05284 if (cp2) 05285 *cp2++ = 0; 05286 len = strtoul(cp, &ecp, 0); 05287 if (*ecp) 05288 goto bad_id; 05289 if (*objidlen + len + 1 >= maxlen) 05290 goto bad_id; 05291 objid[*objidlen] = len; 05292 (*objidlen)++; 05293 cp = cp2; 05294 } 05295 while (len && cp) { 05296 fcp = cp; 05297 cp2 = strchr(cp, '.'); 05298 if (cp2) 05299 *cp2++ = 0; 05300 objid[*objidlen] = strtoul(cp, &ecp, 0); 05301 if (*ecp) 05302 goto bad_id; 05303 if (check && objid[*objidlen] > 255) 05304 goto bad_id; 05305 (*objidlen)++; 05306 len--; 05307 cp = cp2; 05308 } 05309 } 05310 break; 05311 case TYPE_OBJID: 05312 in_dices = NULL; 05313 cp2 = cp; 05314 break; 05315 case TYPE_NETADDR: 05316 fcp = cp; 05317 cp2 = strchr(cp, '.'); 05318 if (cp2) 05319 *cp2++ = 0; 05320 subid = strtoul(cp, &ecp, 0); 05321 if (*ecp) 05322 goto bad_id; 05323 if (*objidlen + 1 >= maxlen) 05324 goto bad_id; 05325 objid[*objidlen] = subid; 05326 (*objidlen)++; 05327 cp = cp2; 05328 if (subid == 1) { 05329 for (len = 0; cp && len < 4; len++) { 05330 fcp = cp; 05331 cp2 = strchr(cp, '.'); 05332 if (cp2) 05333 *cp2++ = 0; 05334 subid = strtoul(cp, &ecp, 0); 05335 if (*ecp) 05336 goto bad_id; 05337 if (*objidlen + 1 >= maxlen) 05338 goto bad_id; 05339 if (check && subid > 255) 05340 goto bad_id; 05341 objid[*objidlen] = subid; 05342 (*objidlen)++; 05343 cp = cp2; 05344 } 05345 } 05346 else { 05347 in_dices = NULL; 05348 } 05349 break; 05350 default: 05351 snmp_log(LOG_ERR, "Unexpected index type: %d %s %s\n", 05352 tp->type, in_dices->ilabel, cp); 05353 in_dices = NULL; 05354 cp2 = cp; 05355 break; 05356 } 05357 cp = cp2; 05358 if (in_dices) 05359 in_dices = in_dices->next; 05360 } 05361 05362 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 05363 while (cp) { 05364 fcp = cp; 05365 switch (*cp) { 05366 case '0': 05367 case '1': 05368 case '2': 05369 case '3': 05370 case '4': 05371 case '5': 05372 case '6': 05373 case '7': 05374 case '8': 05375 case '9': 05376 cp2 = strchr(cp, '.'); 05377 if (cp2) 05378 *cp2++ = 0; 05379 subid = strtoul(cp, &ecp, 0); 05380 if (*ecp) 05381 goto bad_id; 05382 if (*objidlen >= maxlen) 05383 goto bad_id; 05384 objid[*objidlen] = subid; 05385 (*objidlen)++; 05386 break; 05387 case '"': 05388 case '\'': 05389 doingquote = *cp++; 05390 /* 05391 * insert length if requested 05392 */ 05393 if (doingquote == '"') { 05394 if (*objidlen >= maxlen) 05395 goto bad_id; 05396 objid[*objidlen] = len = strchr(cp, doingquote) - cp; 05397 (*objidlen)++; 05398 } 05399 05400 while (*cp && *cp != doingquote) { 05401 if (*objidlen >= maxlen) 05402 goto bad_id; 05403 objid[*objidlen] = *cp++; 05404 (*objidlen)++; 05405 } 05406 if (!cp) 05407 goto bad_id; 05408 cp2 = cp + 1; 05409 if (!*cp2) 05410 cp2 = NULL; 05411 else if (*cp2 == '.') 05412 cp2++; 05413 else 05414 goto bad_id; 05415 break; 05416 default: 05417 goto bad_id; 05418 } 05419 cp = cp2; 05420 } 05421 return 1; 05422 05423 bad_id: 05424 { 05425 char buf[256]; 05426 #ifndef NETSNMP_DISABLE_MIB_LOADING 05427 if (in_dices) 05428 snprintf(buf, sizeof(buf), "Index out of range: %s (%s)", 05429 fcp, in_dices->ilabel); 05430 else if (tp) 05431 snprintf(buf, sizeof(buf), "Sub-id not found: %s -> %s", tp->label, fcp); 05432 else 05433 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 05434 snprintf(buf, sizeof(buf), "%s", fcp); 05435 buf[ sizeof(buf)-1 ] = 0; 05436 05437 snmp_set_detail(buf); 05438 } 05439 return 0; 05440 } 05441 05442 05443 #ifndef NETSNMP_DISABLE_MIB_LOADING 05444 05447 int 05448 get_wild_node(const char *name, oid * objid, size_t * objidlen) 05449 { 05450 struct tree *tp = find_best_tree_node(name, tree_head, NULL); 05451 if (!tp) 05452 return 0; 05453 return get_node(tp->label, objid, objidlen); 05454 } 05455 05456 int 05457 get_node(const char *name, oid * objid, size_t * objidlen) 05458 { 05459 const char *cp; 05460 char ch; 05461 int res; 05462 05463 cp = name; 05464 while ((ch = *cp)) 05465 if (('0' <= ch && ch <= '9') 05466 || ('a' <= ch && ch <= 'z') 05467 || ('A' <= ch && ch <= 'Z') 05468 || ch == '-') 05469 cp++; 05470 else 05471 break; 05472 if (ch != ':') 05473 if (*name == '.') 05474 res = get_module_node(name + 1, "ANY", objid, objidlen); 05475 else 05476 res = get_module_node(name, "ANY", objid, objidlen); 05477 else { 05478 char *module; 05479 /* 05480 * requested name is of the form 05481 * "module:subidentifier" 05482 */ 05483 module = (char *) malloc((size_t) (cp - name + 1)); 05484 if (!module) 05485 return SNMPERR_GENERR; 05486 memcpy(module, name, (size_t) (cp - name)); 05487 module[cp - name] = 0; 05488 cp++; /* cp now point to the subidentifier */ 05489 if (*cp == ':') 05490 cp++; 05491 05492 /* 05493 * 'cp' and 'name' *do* go that way round! 05494 */ 05495 res = get_module_node(cp, module, objid, objidlen); 05496 SNMP_FREE(module); 05497 } 05498 if (res == 0) { 05499 SET_SNMP_ERROR(SNMPERR_UNKNOWN_OBJID); 05500 } 05501 05502 return res; 05503 } 05504 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 05505 05506 #ifdef testing 05507 05508 main(int argc, char *argv[]) 05509 { 05510 oid objid[MAX_OID_LEN]; 05511 int objidlen = MAX_OID_LEN; 05512 int count; 05513 netsnmp_variable_list variable; 05514 05515 netsnmp_init_mib(); 05516 if (argc < 2) 05517 print_subtree(stdout, tree_head, 0); 05518 variable.type = ASN_INTEGER; 05519 variable.val.integer = 3; 05520 variable.val_len = 4; 05521 for (argc--; argc; argc--, argv++) { 05522 objidlen = MAX_OID_LEN; 05523 printf("read_objid(%s) = %d\n", 05524 argv[1], read_objid(argv[1], objid, &objidlen)); 05525 for (count = 0; count < objidlen; count++) 05526 printf("%d.", objid[count]); 05527 printf("\n"); 05528 print_variable(objid, objidlen, &variable); 05529 } 05530 } 05531 05532 #endif /* testing */ 05533 05534 #ifndef NETSNMP_DISABLE_MIB_LOADING 05535 /* 05536 * initialize: no peers included in the report. 05537 */ 05538 void 05539 clear_tree_flags(register struct tree *tp) 05540 { 05541 for (; tp; tp = tp->next_peer) { 05542 tp->reported = 0; 05543 if (tp->child_list) 05544 clear_tree_flags(tp->child_list); 05545 /*RECURSE*/} 05546 } 05547 05548 /* 05549 * Update: 1998-07-17 <jhy@gsu.edu> 05550 * Added print_oid_report* functions. 05551 */ 05552 static int print_subtree_oid_report_labeledoid = 0; 05553 static int print_subtree_oid_report_oid = 0; 05554 static int print_subtree_oid_report_symbolic = 0; 05555 static int print_subtree_oid_report_mibchildoid = 0; 05556 static int print_subtree_oid_report_suffix = 0; 05557 05558 /* 05559 * These methods recurse. 05560 */ 05561 static void print_parent_labeledoid(FILE *, struct tree *); 05562 static void print_parent_oid(FILE *, struct tree *); 05563 static void print_parent_mibchildoid(FILE *, struct tree *); 05564 static void print_parent_label(FILE *, struct tree *); 05565 static void print_subtree_oid_report(FILE *, struct tree *, int); 05566 05567 05568 void 05569 print_oid_report(FILE * fp) 05570 { 05571 struct tree *tp; 05572 clear_tree_flags(tree_head); 05573 for (tp = tree_head; tp; tp = tp->next_peer) 05574 print_subtree_oid_report(fp, tp, 0); 05575 } 05576 05577 void 05578 print_oid_report_enable_labeledoid(void) 05579 { 05580 print_subtree_oid_report_labeledoid = 1; 05581 } 05582 05583 void 05584 print_oid_report_enable_oid(void) 05585 { 05586 print_subtree_oid_report_oid = 1; 05587 } 05588 05589 void 05590 print_oid_report_enable_suffix(void) 05591 { 05592 print_subtree_oid_report_suffix = 1; 05593 } 05594 05595 void 05596 print_oid_report_enable_symbolic(void) 05597 { 05598 print_subtree_oid_report_symbolic = 1; 05599 } 05600 05601 void 05602 print_oid_report_enable_mibchildoid(void) 05603 { 05604 print_subtree_oid_report_mibchildoid = 1; 05605 } 05606 05607 /* 05608 * helper methods for print_subtree_oid_report() 05609 * each one traverses back up the node tree 05610 * until there is no parent. Then, the label combination 05611 * is output, such that the parent is displayed first. 05612 * 05613 * Warning: these methods are all recursive. 05614 */ 05615 05616 static void 05617 print_parent_labeledoid(FILE * f, struct tree *tp) 05618 { 05619 if (tp) { 05620 if (tp->parent) { 05621 print_parent_labeledoid(f, tp->parent); 05622 /*RECURSE*/} 05623 fprintf(f, ".%s(%lu)", tp->label, tp->subid); 05624 } 05625 } 05626 05627 static void 05628 print_parent_oid(FILE * f, struct tree *tp) 05629 { 05630 if (tp) { 05631 if (tp->parent) { 05632 print_parent_oid(f, tp->parent); 05633 /*RECURSE*/} 05634 fprintf(f, ".%lu", tp->subid); 05635 } 05636 } 05637 05638 05639 static void print_parent_mibchildoid(FILE * f, struct tree *tp) 05640 { 05641 static struct tree *temp; 05642 unsigned long elems[100]; 05643 int elem_cnt = 0; 05644 int i = 0; 05645 temp = tp; 05646 if (temp) { 05647 while (temp->parent) { 05648 elems[elem_cnt++] = temp->subid; 05649 temp = temp->parent; 05650 } 05651 elems[elem_cnt++] = temp->subid; 05652 } 05653 for (i = elem_cnt - 1; i >= 0; i--) { 05654 if (i == elem_cnt - 1) { 05655 fprintf(f, "%lu", elems[i]); 05656 } else { 05657 fprintf(f, ".%lu", elems[i]); 05658 } 05659 } 05660 } 05661 05662 static void 05663 print_parent_label(FILE * f, struct tree *tp) 05664 { 05665 if (tp) { 05666 if (tp->parent) { 05667 print_parent_label(f, tp->parent); 05668 /*RECURSE*/} 05669 fprintf(f, ".%s", tp->label); 05670 } 05671 } 05672 05684 static void 05685 print_subtree_oid_report(FILE * f, struct tree *tree, int count) 05686 { 05687 struct tree *tp; 05688 05689 count++; 05690 05691 /* 05692 * sanity check 05693 */ 05694 if (!tree) { 05695 return; 05696 } 05697 05698 /* 05699 * find the not reported peer with the lowest sub-identifier. 05700 * if no more, break the loop and cleanup. 05701 * set "reported" flag, and create report for this peer. 05702 * recurse using the children of this peer, if any. 05703 */ 05704 while (1) { 05705 register struct tree *ntp; 05706 05707 tp = 0; 05708 for (ntp = tree->child_list; ntp; ntp = ntp->next_peer) { 05709 if (ntp->reported) 05710 continue; 05711 05712 if (!tp || (tp->subid > ntp->subid)) 05713 tp = ntp; 05714 } 05715 if (!tp) 05716 break; 05717 05718 tp->reported = 1; 05719 05720 if (print_subtree_oid_report_labeledoid) { 05721 print_parent_labeledoid(f, tp); 05722 fprintf(f, "\n"); 05723 } 05724 if (print_subtree_oid_report_oid) { 05725 print_parent_oid(f, tp); 05726 fprintf(f, "\n"); 05727 } 05728 if (print_subtree_oid_report_symbolic) { 05729 print_parent_label(f, tp); 05730 fprintf(f, "\n"); 05731 } 05732 if (print_subtree_oid_report_mibchildoid) { 05733 fprintf(f, "\"%s\"\t", tp->label); 05734 fprintf(f, "\t\t\""); 05735 print_parent_mibchildoid(f, tp); 05736 fprintf(f, "\"\n"); 05737 } 05738 if (print_subtree_oid_report_suffix) { 05739 int i; 05740 for (i = 0; i < count; i++) 05741 fprintf(f, " "); 05742 fprintf(f, "%s(%ld) type=%d", tp->label, tp->subid, tp->type); 05743 if (tp->tc_index != -1) 05744 fprintf(f, " tc=%d", tp->tc_index); 05745 if (tp->hint) 05746 fprintf(f, " hint=%s", tp->hint); 05747 if (tp->units) 05748 fprintf(f, " units=%s", tp->units); 05749 05750 fprintf(f, "\n"); 05751 } 05752 print_subtree_oid_report(f, tp, count); 05753 /*RECURSE*/} 05754 } 05755 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 05756 05757 05770 char * 05771 uptime_string(u_long timeticks, char *buf) 05772 { 05773 return uptime_string_n( timeticks, buf, 40); 05774 } 05775 05776 char * 05777 uptime_string_n(u_long timeticks, char *buf, size_t buflen) 05778 { 05779 uptimeString(timeticks, buf, buflen); 05780 #ifdef CMU_COMPATIBLE 05781 { 05782 char *cp = strrchr(buf, '.'); 05783 if (cp) 05784 *cp = '\0'; 05785 } 05786 #endif 05787 return buf; 05788 } 05789 05805 oid * 05806 snmp_parse_oid(const char *argv, oid * root, size_t * rootlen) 05807 { 05808 size_t savlen = *rootlen; 05809 static size_t tmpbuf_len = 0; 05810 static char *tmpbuf; 05811 const char *suffix, *prefix; 05812 05813 suffix = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 05814 NETSNMP_DS_LIB_OIDSUFFIX); 05815 prefix = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 05816 NETSNMP_DS_LIB_OIDPREFIX); 05817 if ((suffix && suffix[0]) || (prefix && prefix[0])) { 05818 if (!suffix) 05819 suffix = ""; 05820 if (!prefix) 05821 prefix = ""; 05822 if ((strlen(suffix) + strlen(prefix) + strlen(argv) + 2) > tmpbuf_len) { 05823 tmpbuf_len = strlen(suffix) + strlen(argv) + strlen(prefix) + 2; 05824 tmpbuf = (char *)realloc(tmpbuf, tmpbuf_len); 05825 } 05826 snprintf(tmpbuf, tmpbuf_len, "%s%s%s%s", prefix, argv, 05827 ((suffix[0] == '.' || suffix[0] == '\0') ? "" : "."), 05828 suffix); 05829 argv = tmpbuf; 05830 DEBUGMSGTL(("snmp_parse_oid","Parsing: %s\n",argv)); 05831 } 05832 05833 #ifndef NETSNMP_DISABLE_MIB_LOADING 05834 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_RANDOM_ACCESS) 05835 || strchr(argv, ':')) { 05836 if (get_node(argv, root, rootlen)) { 05837 return root; 05838 } 05839 } else if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REGEX_ACCESS)) { 05840 clear_tree_flags(tree_head); 05841 if (get_wild_node(argv, root, rootlen)) { 05842 return root; 05843 } 05844 } else { 05845 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 05846 if (read_objid(argv, root, rootlen)) { 05847 return root; 05848 } 05849 #ifndef NETSNMP_DISABLE_MIB_LOADING 05850 *rootlen = savlen; 05851 if (get_node(argv, root, rootlen)) { 05852 return root; 05853 } 05854 *rootlen = savlen; 05855 DEBUGMSGTL(("parse_oid", "wildly parsing\n")); 05856 clear_tree_flags(tree_head); 05857 if (get_wild_node(argv, root, rootlen)) { 05858 return root; 05859 } 05860 } 05861 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 05862 return NULL; 05863 } 05864 05865 #ifndef NETSNMP_DISABLE_MIB_LOADING 05866 /* 05867 * Use DISPLAY-HINT to parse a value into an octet string. 05868 * 05869 * note that "1d1d", "11" could have come from an octet string that 05870 * looked like { 1, 1 } or an octet string that looked like { 11 } 05871 * because of this, it's doubtful that anyone would use such a display 05872 * string. Therefore, the parser ignores this case. 05873 */ 05874 05875 struct parse_hints { 05876 int length; 05877 int repeat; 05878 int format; 05879 int separator; 05880 int terminator; 05881 unsigned char *result; 05882 int result_max; 05883 int result_len; 05884 }; 05885 05886 static void parse_hints_reset(struct parse_hints *ph) 05887 { 05888 ph->length = 0; 05889 ph->repeat = 0; 05890 ph->format = 0; 05891 ph->separator = 0; 05892 ph->terminator = 0; 05893 } 05894 05895 static void parse_hints_ctor(struct parse_hints *ph) 05896 { 05897 parse_hints_reset(ph); 05898 ph->result = NULL; 05899 ph->result_max = 0; 05900 ph->result_len = 0; 05901 } 05902 05903 static int parse_hints_add_result_octet(struct parse_hints *ph, unsigned char octet) 05904 { 05905 if (!(ph->result_len < ph->result_max)) { 05906 ph->result_max = ph->result_len + 32; 05907 if (!ph->result) { 05908 ph->result = (unsigned char *)malloc(ph->result_max); 05909 } else { 05910 ph->result = (unsigned char *)realloc(ph->result, ph->result_max); 05911 } 05912 } 05913 05914 if (!ph->result) { 05915 return 0; /* failed */ 05916 } 05917 05918 ph->result[ph->result_len++] = octet; 05919 return 1; /* success */ 05920 } 05921 05922 static int parse_hints_parse(struct parse_hints *ph, const char **v_in_out) 05923 { 05924 const char *v = *v_in_out; 05925 char *nv; 05926 int base; 05927 int repeats = 0; 05928 int repeat_fixup = ph->result_len; 05929 05930 if (ph->repeat) { 05931 if (!parse_hints_add_result_octet(ph, 0)) { 05932 return 0; 05933 } 05934 } 05935 do { 05936 base = 0; 05937 switch (ph->format) { 05938 case 'x': base += 6; /* fall through */ 05939 case 'd': base += 2; /* fall through */ 05940 case 'o': base += 8; /* fall through */ 05941 { 05942 int i; 05943 unsigned long number = strtol(v, &nv, base); 05944 if (nv == v) return 0; 05945 v = nv; 05946 for (i = 0; i < ph->length; i++) { 05947 int shift = 8 * (ph->length - 1 - i); 05948 if (!parse_hints_add_result_octet(ph, (u_char)(number >> shift) )) { 05949 return 0; /* failed */ 05950 } 05951 } 05952 } 05953 break; 05954 05955 case 'a': 05956 { 05957 int i; 05958 05959 for (i = 0; i < ph->length && *v; i++) { 05960 if (!parse_hints_add_result_octet(ph, *v++)) { 05961 return 0; /* failed */ 05962 } 05963 } 05964 } 05965 break; 05966 } 05967 05968 repeats++; 05969 05970 if (ph->separator && *v) { 05971 if (*v == ph->separator) { 05972 v++; 05973 } else { 05974 return 0; /* failed */ 05975 } 05976 } 05977 05978 if (ph->terminator) { 05979 if (*v == ph->terminator) { 05980 v++; 05981 break; 05982 } 05983 } 05984 } while (ph->repeat && *v); 05985 if (ph->repeat) { 05986 ph->result[repeat_fixup] = repeats; 05987 } 05988 05989 *v_in_out = v; 05990 return 1; 05991 } 05992 05993 static void parse_hints_length_add_digit(struct parse_hints *ph, int digit) 05994 { 05995 ph->length *= 10; 05996 ph->length += digit - '0'; 05997 } 05998 05999 const char *parse_octet_hint(const char *hint, const char *value, unsigned char **new_val, int *new_val_len) 06000 { 06001 const char *h = hint; 06002 const char *v = value; 06003 struct parse_hints ph; 06004 int retval = 1; 06005 /* See RFC 1443 */ 06006 enum { 06007 HINT_1_2, 06008 HINT_2_3, 06009 HINT_1_2_4, 06010 HINT_1_2_5 06011 } state = HINT_1_2; 06012 06013 parse_hints_ctor(&ph); 06014 while (*h && *v && retval) { 06015 switch (state) { 06016 case HINT_1_2: 06017 if ('*' == *h) { 06018 ph.repeat = 1; 06019 state = HINT_2_3; 06020 } else if (isdigit(*h)) { 06021 parse_hints_length_add_digit(&ph, *h); 06022 state = HINT_2_3; 06023 } else { 06024 return v; /* failed */ 06025 } 06026 break; 06027 06028 case HINT_2_3: 06029 if (isdigit(*h)) { 06030 parse_hints_length_add_digit(&ph, *h); 06031 /* state = HINT_2_3 */ 06032 } else if ('x' == *h || 'd' == *h || 'o' == *h || 'a' == *h) { 06033 ph.format = *h; 06034 state = HINT_1_2_4; 06035 } else { 06036 return v; /* failed */ 06037 } 06038 break; 06039 06040 case HINT_1_2_4: 06041 if ('*' == *h) { 06042 retval = parse_hints_parse(&ph, &v); 06043 parse_hints_reset(&ph); 06044 06045 ph.repeat = 1; 06046 state = HINT_2_3; 06047 } else if (isdigit(*h)) { 06048 retval = parse_hints_parse(&ph, &v); 06049 parse_hints_reset(&ph); 06050 06051 parse_hints_length_add_digit(&ph, *h); 06052 state = HINT_2_3; 06053 } else { 06054 ph.separator = *h; 06055 state = HINT_1_2_5; 06056 } 06057 break; 06058 06059 case HINT_1_2_5: 06060 if ('*' == *h) { 06061 retval = parse_hints_parse(&ph, &v); 06062 parse_hints_reset(&ph); 06063 06064 ph.repeat = 1; 06065 state = HINT_2_3; 06066 } else if (isdigit(*h)) { 06067 retval = parse_hints_parse(&ph, &v); 06068 parse_hints_reset(&ph); 06069 06070 parse_hints_length_add_digit(&ph, *h); 06071 state = HINT_2_3; 06072 } else { 06073 ph.terminator = *h; 06074 06075 retval = parse_hints_parse(&ph, &v); 06076 parse_hints_reset(&ph); 06077 06078 state = HINT_1_2; 06079 } 06080 break; 06081 } 06082 h++; 06083 } 06084 while (*v && retval) { 06085 retval = parse_hints_parse(&ph, &v); 06086 } 06087 if (retval) { 06088 *new_val = ph.result; 06089 *new_val_len = ph.result_len; 06090 } else { 06091 if (ph.result) { 06092 SNMP_FREE(ph.result); 06093 } 06094 *new_val = NULL; 06095 *new_val_len = 0; 06096 } 06097 return retval ? NULL : v; 06098 } 06099 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 06100 06101 #ifdef test_display_hint 06102 06103 int main(int argc, const char **argv) 06104 { 06105 const char *hint; 06106 const char *value; 06107 unsigned char *new_val; 06108 int new_val_len; 06109 char *r; 06110 06111 if (argc < 3) { 06112 fprintf(stderr, "usage: dh <hint> <value>\n"); 06113 exit(2); 06114 } 06115 hint = argv[1]; 06116 value = argv[2]; 06117 r = parse_octet_hint(hint, value, &new_val, &new_val_len); 06118 printf("{\"%s\", \"%s\"}: \n\t", hint, value); 06119 if (r) { 06120 *r = 0; 06121 printf("returned failed\n"); 06122 printf("value syntax error at: %s\n", value); 06123 } 06124 else { 06125 int i; 06126 printf("returned success\n"); 06127 for (i = 0; i < new_val_len; i++) { 06128 int c = new_val[i] & 0xFF; 06129 printf("%02X(%c) ", c, isprint(c) ? c : ' '); 06130 } 06131 SNMP_FREE(new_val); 06132 } 06133 printf("\n"); 06134 exit(0); 06135 } 06136 06137 #endif /* test_display_hint */ 06138 06139 u_char 06140 mib_to_asn_type(int mib_type) 06141 { 06142 switch (mib_type) { 06143 case TYPE_OBJID: 06144 return ASN_OBJECT_ID; 06145 06146 case TYPE_OCTETSTR: 06147 return ASN_OCTET_STR; 06148 06149 case TYPE_NETADDR: 06150 case TYPE_IPADDR: 06151 return ASN_IPADDRESS; 06152 06153 case TYPE_INTEGER32: 06154 case TYPE_INTEGER: 06155 return ASN_INTEGER; 06156 06157 case TYPE_COUNTER: 06158 return ASN_COUNTER; 06159 06160 case TYPE_GAUGE: 06161 return ASN_GAUGE; 06162 06163 case TYPE_TIMETICKS: 06164 return ASN_TIMETICKS; 06165 06166 case TYPE_OPAQUE: 06167 return ASN_OPAQUE; 06168 06169 case TYPE_NULL: 06170 return ASN_NULL; 06171 06172 case TYPE_COUNTER64: 06173 return ASN_COUNTER64; 06174 06175 case TYPE_BITSTRING: 06176 return ASN_BIT_STR; 06177 06178 case TYPE_UINTEGER: 06179 case TYPE_UNSIGNED32: 06180 return ASN_UNSIGNED; 06181 06182 case TYPE_NSAPADDRESS: 06183 return ASN_NSAP; 06184 06185 } 06186 return -1; 06187 } 06188 06199 int 06200 netsnmp_str2oid(const char *S, oid * O, int L) 06201 { 06202 const char *c = S; 06203 oid *o = &O[1]; 06204 06205 --L; /* leave room for length prefix */ 06206 06207 for (; *c && L; --L, ++o, ++c) 06208 *o = *c; 06209 06210 /* 06211 * make sure we got to the end of the string 06212 */ 06213 if (*c != 0) 06214 return 1; 06215 06216 /* 06217 * set the length of the oid 06218 */ 06219 *O = c - S; 06220 06221 return 0; 06222 } 06223 06234 int 06235 netsnmp_oid2chars(char *C, int L, const oid * O) 06236 { 06237 char *c = C; 06238 const oid *o = &O[1]; 06239 06240 if (L < (int)*O) 06241 return 1; 06242 06243 L = *O; 06244 for (; L; --L, ++o, ++c) { 06245 if (*o > 0xFF) 06246 return 1; 06247 *c = (char)*o; 06248 } 06249 return 0; 06250 } 06251 06262 int 06263 netsnmp_oid2str(char *S, int L, oid * O) 06264 { 06265 int rc; 06266 06267 if (L <= (int)*O) 06268 return 1; 06269 06270 rc = netsnmp_oid2chars(S, L, O); 06271 if (rc) 06272 return 1; 06273 06274 S[ *O ] = 0; 06275 06276 return 0; 06277 } 06278 06279 int 06280 snprint_by_type(char *buf, size_t buf_len, 06281 netsnmp_variable_list * var, 06282 const struct enum_list *enums, 06283 const char *hint, const char *units) 06284 { 06285 size_t out_len = 0; 06286 if (sprint_realloc_by_type((u_char **) & buf, &buf_len, &out_len, 0, 06287 var, enums, hint, units)) 06288 return (int) out_len; 06289 else 06290 return -1; 06291 } 06292 06293 int 06294 snprint_hexstring(char *buf, size_t buf_len, const u_char * cp, size_t len) 06295 { 06296 size_t out_len = 0; 06297 if (sprint_realloc_hexstring((u_char **) & buf, &buf_len, &out_len, 0, 06298 cp, len)) 06299 return (int) out_len; 06300 else 06301 return -1; 06302 } 06303 06304 int 06305 snprint_asciistring(char *buf, size_t buf_len, 06306 const u_char * cp, size_t len) 06307 { 06308 size_t out_len = 0; 06309 if (sprint_realloc_asciistring 06310 ((u_char **) & buf, &buf_len, &out_len, 0, cp, len)) 06311 return (int) out_len; 06312 else 06313 return -1; 06314 } 06315 06316 int 06317 snprint_octet_string(char *buf, size_t buf_len, 06318 const netsnmp_variable_list * var, const struct enum_list *enums, 06319 const char *hint, const char *units) 06320 { 06321 size_t out_len = 0; 06322 if (sprint_realloc_octet_string 06323 ((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint, 06324 units)) 06325 return (int) out_len; 06326 else 06327 return -1; 06328 } 06329 06330 int 06331 snprint_opaque(char *buf, size_t buf_len, 06332 const netsnmp_variable_list * var, const struct enum_list *enums, 06333 const char *hint, const char *units) 06334 { 06335 size_t out_len = 0; 06336 if (sprint_realloc_opaque((u_char **) & buf, &buf_len, &out_len, 0, 06337 var, enums, hint, units)) 06338 return (int) out_len; 06339 else 06340 return -1; 06341 } 06342 06343 int 06344 snprint_object_identifier(char *buf, size_t buf_len, 06345 const netsnmp_variable_list * var, 06346 const struct enum_list *enums, const char *hint, 06347 const char *units) 06348 { 06349 size_t out_len = 0; 06350 if (sprint_realloc_object_identifier 06351 ((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint, 06352 units)) 06353 return (int) out_len; 06354 else 06355 return -1; 06356 } 06357 06358 int 06359 snprint_timeticks(char *buf, size_t buf_len, 06360 const netsnmp_variable_list * var, const struct enum_list *enums, 06361 const char *hint, const char *units) 06362 { 06363 size_t out_len = 0; 06364 if (sprint_realloc_timeticks((u_char **) & buf, &buf_len, &out_len, 0, 06365 var, enums, hint, units)) 06366 return (int) out_len; 06367 else 06368 return -1; 06369 } 06370 06371 int 06372 snprint_hinted_integer(char *buf, size_t buf_len, 06373 long val, const char *hint, const char *units) 06374 { 06375 size_t out_len = 0; 06376 if (sprint_realloc_hinted_integer 06377 ((u_char **) & buf, &buf_len, &out_len, 0, val, 'd', hint, units)) 06378 return (int) out_len; 06379 else 06380 return -1; 06381 } 06382 06383 int 06384 snprint_integer(char *buf, size_t buf_len, 06385 const netsnmp_variable_list * var, const struct enum_list *enums, 06386 const char *hint, const char *units) 06387 { 06388 size_t out_len = 0; 06389 if (sprint_realloc_integer((u_char **) & buf, &buf_len, &out_len, 0, 06390 var, enums, hint, units)) 06391 return (int) out_len; 06392 else 06393 return -1; 06394 } 06395 06396 int 06397 snprint_uinteger(char *buf, size_t buf_len, 06398 const netsnmp_variable_list * var, const struct enum_list *enums, 06399 const char *hint, const char *units) 06400 { 06401 size_t out_len = 0; 06402 if (sprint_realloc_uinteger((u_char **) & buf, &buf_len, &out_len, 0, 06403 var, enums, hint, units)) 06404 return (int) out_len; 06405 else 06406 return -1; 06407 } 06408 06409 int 06410 snprint_gauge(char *buf, size_t buf_len, 06411 const netsnmp_variable_list * var, const struct enum_list *enums, 06412 const char *hint, const char *units) 06413 { 06414 size_t out_len = 0; 06415 if (sprint_realloc_gauge((u_char **) & buf, &buf_len, &out_len, 0, 06416 var, enums, hint, units)) 06417 return (int) out_len; 06418 else 06419 return -1; 06420 } 06421 06422 int 06423 snprint_counter(char *buf, size_t buf_len, 06424 const netsnmp_variable_list * var, const struct enum_list *enums, 06425 const char *hint, const char *units) 06426 { 06427 size_t out_len = 0; 06428 if (sprint_realloc_counter((u_char **) & buf, &buf_len, &out_len, 0, 06429 var, enums, hint, units)) 06430 return (int) out_len; 06431 else 06432 return -1; 06433 } 06434 06435 int 06436 snprint_networkaddress(char *buf, size_t buf_len, 06437 const netsnmp_variable_list * var, 06438 const struct enum_list *enums, const char *hint, 06439 const char *units) 06440 { 06441 size_t out_len = 0; 06442 if (sprint_realloc_networkaddress 06443 ((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint, 06444 units)) 06445 return (int) out_len; 06446 else 06447 return -1; 06448 } 06449 06450 int 06451 snprint_ipaddress(char *buf, size_t buf_len, 06452 const netsnmp_variable_list * var, const struct enum_list *enums, 06453 const char *hint, const char *units) 06454 { 06455 size_t out_len = 0; 06456 if (sprint_realloc_ipaddress((u_char **) & buf, &buf_len, &out_len, 0, 06457 var, enums, hint, units)) 06458 return (int) out_len; 06459 else 06460 return -1; 06461 } 06462 06463 int 06464 snprint_null(char *buf, size_t buf_len, 06465 const netsnmp_variable_list * var, const struct enum_list *enums, 06466 const char *hint, const char *units) 06467 { 06468 size_t out_len = 0; 06469 if (sprint_realloc_null((u_char **) & buf, &buf_len, &out_len, 0, 06470 var, enums, hint, units)) 06471 return (int) out_len; 06472 else 06473 return -1; 06474 } 06475 06476 int 06477 snprint_bitstring(char *buf, size_t buf_len, 06478 const netsnmp_variable_list * var, const struct enum_list *enums, 06479 const char *hint, const char *units) 06480 { 06481 size_t out_len = 0; 06482 if (sprint_realloc_bitstring((u_char **) & buf, &buf_len, &out_len, 0, 06483 var, enums, hint, units)) 06484 return (int) out_len; 06485 else 06486 return -1; 06487 } 06488 06489 int 06490 snprint_nsapaddress(char *buf, size_t buf_len, 06491 const netsnmp_variable_list * var, const struct enum_list *enums, 06492 const char *hint, const char *units) 06493 { 06494 size_t out_len = 0; 06495 if (sprint_realloc_nsapaddress 06496 ((u_char **) & buf, &buf_len, &out_len, 0, var, enums, hint, 06497 units)) 06498 return (int) out_len; 06499 else 06500 return -1; 06501 } 06502 06503 int 06504 snprint_counter64(char *buf, size_t buf_len, 06505 const netsnmp_variable_list * var, const struct enum_list *enums, 06506 const char *hint, const char *units) 06507 { 06508 size_t out_len = 0; 06509 if (sprint_realloc_counter64((u_char **) & buf, &buf_len, &out_len, 0, 06510 var, enums, hint, units)) 06511 return (int) out_len; 06512 else 06513 return -1; 06514 } 06515 06516 int 06517 snprint_badtype(char *buf, size_t buf_len, 06518 const netsnmp_variable_list * var, const struct enum_list *enums, 06519 const char *hint, const char *units) 06520 { 06521 size_t out_len = 0; 06522 if (sprint_realloc_badtype((u_char **) & buf, &buf_len, &out_len, 0, 06523 var, enums, hint, units)) 06524 return (int) out_len; 06525 else 06526 return -1; 06527 } 06528 06529 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 06530 int 06531 snprint_float(char *buf, size_t buf_len, 06532 const netsnmp_variable_list * var, const struct enum_list *enums, 06533 const char *hint, const char *units) 06534 { 06535 size_t out_len = 0; 06536 if (sprint_realloc_float((u_char **) & buf, &buf_len, &out_len, 0, 06537 var, enums, hint, units)) 06538 return (int) out_len; 06539 else 06540 return -1; 06541 } 06542 06543 int 06544 snprint_double(char *buf, size_t buf_len, 06545 const netsnmp_variable_list * var, const struct enum_list *enums, 06546 const char *hint, const char *units) 06547 { 06548 size_t out_len = 0; 06549 if (sprint_realloc_double((u_char **) & buf, &buf_len, &out_len, 0, 06550 var, enums, hint, units)) 06551 return (int) out_len; 06552 else 06553 return -1; 06554 } 06555 #endif 06556