mib.c
上传用户:cxs890
上传日期:2021-05-22
资源大小:347k
文件大小:65k
源码类别:

SNMP编程

开发平台:

C/C++

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