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