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