agent_index.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:27k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * agent_index.c
  3.  *
  4.  * Maintain a registry of index allocations
  5.  *      (Primarily required for AgentX support,
  6.  *       but it could be more widely useable).
  7.  */
  8. #include <net-snmp/net-snmp-config.h>
  9. #include <signal.h>
  10. #if HAVE_STRING_H
  11. #include <string.h>
  12. #endif
  13. #if HAVE_STDLIB_H
  14. #include <stdlib.h>
  15. #endif
  16. #include <sys/types.h>
  17. #include <stdio.h>
  18. #include <fcntl.h>
  19. #if HAVE_WINSOCK_H
  20. #include <winsock.h>
  21. #endif
  22. #if TIME_WITH_SYS_TIME
  23. # ifdef WIN32
  24. #  include <sys/timeb.h>
  25. # else
  26. #  include <sys/time.h>
  27. # endif
  28. # include <time.h>
  29. #else
  30. # if HAVE_SYS_TIME_H
  31. #  include <sys/time.h>
  32. # else
  33. #  include <time.h>
  34. # endif
  35. #endif
  36. #if HAVE_NETINET_IN_H
  37. #include <netinet/in.h>
  38. #endif
  39. #if HAVE_DMALLOC_H
  40. #include <dmalloc.h>
  41. #endif
  42. #include <net-snmp/net-snmp-includes.h>
  43. #include <net-snmp/agent/net-snmp-agent-includes.h>
  44. #include <net-snmp/agent/agent_callbacks.h>
  45. #include <net-snmp/agent/agent_index.h>
  46. #include "snmpd.h"
  47. #include "mibgroup/struct.h"
  48. #include <net-snmp/agent/table.h>
  49. #include <net-snmp/agent/table_iterator.h>
  50. #include "mib_module_includes.h"
  51. #ifdef USING_AGENTX_SUBAGENT_MODULE
  52. #include "agentx/subagent.h"
  53. #include "agentx/client.h"
  54. #endif
  55.         /*
  56.          * Initial support for index allocation
  57.          */
  58. struct snmp_index {
  59.     netsnmp_variable_list *varbind;     /* or pointer to var_list ? */
  60.     int             allocated;
  61.     netsnmp_session *session;
  62.     struct snmp_index *next_oid;
  63.     struct snmp_index *prev_oid;
  64.     struct snmp_index *next_idx;
  65. }              *snmp_index_head = NULL;
  66. extern netsnmp_session *main_session;
  67. /*
  68.  * The caller is responsible for free()ing the memory returned by
  69.  * this function.  
  70.  */
  71. char           *
  72. register_string_index(oid * name, size_t name_len, char *cp)
  73. {
  74.     netsnmp_variable_list varbind, *res;
  75.     memset(&varbind, 0, sizeof(netsnmp_variable_list));
  76.     varbind.type = ASN_OCTET_STR;
  77.     snmp_set_var_objid(&varbind, name, name_len);
  78.     if (cp != ANY_STRING_INDEX) {
  79.         snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
  80.         res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
  81.     } else {
  82.         res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
  83.     }
  84.     if (res == NULL) {
  85.         return NULL;
  86.     } else {
  87.         char           *rv = strdup(res->val.string);
  88.         free(res);
  89.         return rv;
  90.     }
  91. }
  92. int
  93. register_int_index(oid * name, size_t name_len, int val)
  94. {
  95.     netsnmp_variable_list varbind, *res;
  96.     memset(&varbind, 0, sizeof(netsnmp_variable_list));
  97.     varbind.type = ASN_INTEGER;
  98.     snmp_set_var_objid(&varbind, name, name_len);
  99.     varbind.val.string = varbind.buf;
  100.     if (val != ANY_INTEGER_INDEX) {
  101.         varbind.val_len = sizeof(long);
  102.         *varbind.val.integer = val;
  103.         res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
  104.     } else {
  105.         res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
  106.     }
  107.     if (res == NULL) {
  108.         return -1;
  109.     } else {
  110.         int             rv = *(res->val.integer);
  111.         free(res);
  112.         return rv;
  113.     }
  114. }
  115. /*
  116.  * The caller is responsible for free()ing the memory returned by
  117.  * this function.  
  118.  */
  119. netsnmp_variable_list *
  120. register_oid_index(oid * name, size_t name_len,
  121.                    oid * value, size_t value_len)
  122. {
  123.     netsnmp_variable_list varbind;
  124.     memset(&varbind, 0, sizeof(netsnmp_variable_list));
  125.     varbind.type = ASN_OBJECT_ID;
  126.     snmp_set_var_objid(&varbind, name, name_len);
  127.     if (value != ANY_OID_INDEX) {
  128.         snmp_set_var_value(&varbind, (u_char *) value,
  129.                            value_len * sizeof(oid));
  130.         return register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
  131.     } else {
  132.         return register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
  133.     }
  134. }
  135. /*
  136.  * The caller is responsible for free()ing the memory returned by
  137.  * this function.  
  138.  */
  139. netsnmp_variable_list *
  140. register_index(netsnmp_variable_list * varbind, int flags,
  141.                netsnmp_session * ss)
  142. {
  143.     netsnmp_variable_list *rv = NULL;
  144.     struct snmp_index *new_index, *idxptr, *idxptr2;
  145.     struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
  146.     int             res, res2, i;
  147.     DEBUGMSGTL(("register_index", "register "));
  148.     DEBUGMSGVAR(("register_index", varbind));
  149.     DEBUGMSG(("register_index", "for session %08pn", ss));
  150. #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
  151.     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
  152.        NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
  153.         return (agentx_register_index(ss, varbind, flags));
  154.     }
  155. #endif
  156.     /*
  157.      * Look for the requested OID entry 
  158.      */
  159.     prev_oid_ptr = NULL;
  160.     prev_idx_ptr = NULL;
  161.     res = 1;
  162.     res2 = 1;
  163.     for (idxptr = snmp_index_head; idxptr != NULL;
  164.          prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
  165.         if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
  166.                                     idxptr->varbind->name,
  167.                                     idxptr->varbind->name_length)) <= 0)
  168.             break;
  169.     }
  170.     /*
  171.      * Found the OID - now look at the registered indices 
  172.      */
  173.     if (res == 0 && idxptr) {
  174.         if (varbind->type != idxptr->varbind->type)
  175.             return NULL;        /* wrong type */
  176.         /*
  177.          * If we've been asked for an arbitrary new value,
  178.          *      then find the end of the list.
  179.          * If we've been asked for any arbitrary value,
  180.          *      then look for an unused entry, and use that.
  181.          *      If there aren't any, continue as for new.
  182.          * Otherwise, locate the given value in the (sorted)
  183.          *      list of already allocated values
  184.          */
  185.         if (flags & ALLOCATE_ANY_INDEX) {
  186.             for (idxptr2 = idxptr; idxptr2 != NULL;
  187.                  prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
  188.                 if (flags == ALLOCATE_ANY_INDEX && !(idxptr2->allocated)) {
  189.                     if ((rv =
  190.                          snmp_clone_varbind(idxptr2->varbind)) != NULL) {
  191.                         idxptr2->session = ss;
  192.                         idxptr2->allocated = 1;
  193.                     }
  194.                     return rv;
  195.                 }
  196.             }
  197.         } else {
  198.             for (idxptr2 = idxptr; idxptr2 != NULL;
  199.                  prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
  200.                 switch (varbind->type) {
  201.                 case ASN_INTEGER:
  202.                     res2 =
  203.                         (*varbind->val.integer -
  204.                          *idxptr2->varbind->val.integer);
  205.                     break;
  206.                 case ASN_OCTET_STR:
  207.                     i = SNMP_MIN(varbind->val_len,
  208.                                  idxptr2->varbind->val_len);
  209.                     res2 =
  210.                         memcmp(varbind->val.string,
  211.                                idxptr2->varbind->val.string, i);
  212.                     break;
  213.                 case ASN_OBJECT_ID:
  214.                     res2 =
  215.                         snmp_oid_compare(varbind->val.objid,
  216.                                          varbind->val_len / sizeof(oid),
  217.                                          idxptr2->varbind->val.objid,
  218.                                          idxptr2->varbind->val_len /
  219.                                          sizeof(oid));
  220.                     break;
  221.                 default:
  222.                     return NULL;        /* wrong type */
  223.                 }
  224.                 if (res2 <= 0)
  225.                     break;
  226.             }
  227.             if (res2 == 0) {
  228.                 if (idxptr2->allocated) {
  229.                     /*
  230.                      * No good: the index is in use.  
  231.                      */
  232.                     return NULL;
  233.                 } else {
  234.                     /*
  235.                      * Okay, it's unallocated, we can just claim ownership
  236.                      * here.  
  237.                      */
  238.                     if ((rv =
  239.                          snmp_clone_varbind(idxptr2->varbind)) != NULL) {
  240.                         idxptr2->session = ss;
  241.                         idxptr2->allocated = 1;
  242.                     }
  243.                     return rv;
  244.                 }
  245.             }
  246.         }
  247.     }
  248.     /*
  249.      * OK - we've now located where the new entry needs to
  250.      *      be fitted into the index registry tree          
  251.      * To recap:
  252.      *      'prev_oid_ptr' points to the head of the OID index
  253.      *          list prior to this one.  If this is null, then
  254.      *          it means that this is the first OID in the list.
  255.      *      'idxptr' points either to the head of this OID list,
  256.      *          or the next OID (if this is a new OID request)
  257.      *          These can be distinguished by the value of 'res'.
  258.      *
  259.      *      'prev_idx_ptr' points to the index entry that sorts
  260.      *          immediately prior to the requested value (if any).
  261.      *          If an arbitrary value is required, then this will
  262.      *          point to the last allocated index.
  263.      *          If this pointer is null, then either this is a new
  264.      *          OID request, or the requested value is the first
  265.      *          in the list.
  266.      *      'idxptr2' points to the next sorted index (if any)
  267.      *          but is not actually needed any more.
  268.      *
  269.      *  Clear?  Good!
  270.      *      I hope you've been paying attention.
  271.      *          There'll be a test later :-)
  272.      */
  273.     /*
  274.      *      We proceed by creating the new entry
  275.      *         (by copying the entry provided)
  276.      */
  277.     new_index = (struct snmp_index *) calloc(1, sizeof(struct snmp_index));
  278.     if (new_index == NULL)
  279.         return NULL;
  280.     if (0 == snmp_varlist_add_variable(&new_index->varbind,
  281.                                        varbind->name,
  282.                                        varbind->name_length,
  283.                                        varbind->type,
  284.                                        varbind->val.string,
  285.                                        varbind->val_len)) {
  286.         /*
  287.          * if (snmp_clone_var( varbind, new_index->varbind ) != 0 ) 
  288.          */
  289.         free(new_index);
  290.         return NULL;
  291.     }
  292.     new_index->session = ss;
  293.     new_index->allocated = 1;
  294.     if (varbind->type == ASN_OCTET_STR && flags == ALLOCATE_THIS_INDEX)
  295.         new_index->varbind->val.string[new_index->varbind->val_len] = 0;
  296.     /*
  297.      * If we've been given a value, then we can use that, but
  298.      *    otherwise, we need to create a new value for this entry.
  299.      * Note that ANY_INDEX and NEW_INDEX are both covered by this
  300.      *   test (since NEW_INDEX & ANY_INDEX = ANY_INDEX, remember?)
  301.      */
  302.     if (flags & ALLOCATE_ANY_INDEX) {
  303.         if (prev_idx_ptr) {
  304.             if (snmp_clone_var(prev_idx_ptr->varbind, new_index->varbind)
  305.                 != 0) {
  306.                 free(new_index);
  307.                 return NULL;
  308.             }
  309.         } else
  310.             new_index->varbind->val.string = new_index->varbind->buf;
  311.         switch (varbind->type) {
  312.         case ASN_INTEGER:
  313.             if (prev_idx_ptr) {
  314.                 (*new_index->varbind->val.integer)++;
  315.             } else
  316.                 *(new_index->varbind->val.integer) = 1;
  317.             new_index->varbind->val_len = sizeof(long);
  318.             break;
  319.         case ASN_OCTET_STR:
  320.             if (prev_idx_ptr) {
  321.                 i = new_index->varbind->val_len - 1;
  322.                 while (new_index->varbind->buf[i] == 'z') {
  323.                     new_index->varbind->buf[i] = 'a';
  324.                     i--;
  325.                     if (i < 0) {
  326.                         i = new_index->varbind->val_len;
  327.                         new_index->varbind->buf[i] = 'a';
  328.                         new_index->varbind->buf[i + 1] = 0;
  329.                     }
  330.                 }
  331.                 new_index->varbind->buf[i]++;
  332.             } else
  333.                 strcpy((char *) new_index->varbind->buf, "aaaa");
  334.             new_index->varbind->val_len =
  335.                 strlen((char *) new_index->varbind->buf);
  336.             break;
  337.         case ASN_OBJECT_ID:
  338.             if (prev_idx_ptr) {
  339.                 i = prev_idx_ptr->varbind->val_len / sizeof(oid) - 1;
  340.                 while (new_index->varbind->val.objid[i] == 255) {
  341.                     new_index->varbind->val.objid[i] = 1;
  342.                     i--;
  343.                     if (i == 0 && new_index->varbind->val.objid[0] == 2) {
  344.                         new_index->varbind->val.objid[0] = 1;
  345.                         i = new_index->varbind->val_len / sizeof(oid);
  346.                         new_index->varbind->val.objid[i] = 0;
  347.                         new_index->varbind->val_len += sizeof(oid);
  348.                     }
  349.                 }
  350.                 new_index->varbind->val.objid[i]++;
  351.             } else {
  352.                 /*
  353.                  * If the requested OID name is small enough,
  354.                  * *   append another OID (1) and use this as the
  355.                  * *   default starting value for new indexes.
  356.                  */
  357.                 if ((varbind->name_length + 1) * sizeof(oid) <= 40) {
  358.                     for (i = 0; i < (int) varbind->name_length; i++)
  359.                         new_index->varbind->val.objid[i] =
  360.                             varbind->name[i];
  361.                     new_index->varbind->val.objid[varbind->name_length] =
  362.                         1;
  363.                     new_index->varbind->val_len =
  364.                         (varbind->name_length + 1) * sizeof(oid);
  365.                 } else {
  366.                     /*
  367.                      * Otherwise use '.1.1.1.1...' 
  368.                      */
  369.                     i = 40 / sizeof(oid);
  370.                     if (i > 4)
  371.                         i = 4;
  372.                     new_index->varbind->val_len = i * (sizeof(oid));
  373.                     for (i--; i >= 0; i--)
  374.                         new_index->varbind->val.objid[i] = 1;
  375.                 }
  376.             }
  377.             break;
  378.         default:
  379.             snmp_free_var(new_index->varbind);
  380.             free(new_index);
  381.             return NULL;        /* Index type not supported */
  382.         }
  383.     }
  384.     /*
  385.      * Try to duplicate the new varbind for return.  
  386.      */
  387.     if ((rv = snmp_clone_varbind(new_index->varbind)) == NULL) {
  388.         snmp_free_var(new_index->varbind);
  389.         free(new_index);
  390.         return NULL;
  391.     }
  392.     /*
  393.      * Right - we've set up the new entry.
  394.      * All that remains is to link it into the tree.
  395.      * There are a number of possible cases here,
  396.      *   so watch carefully.
  397.      */
  398.     if (prev_idx_ptr) {
  399.         new_index->next_idx = prev_idx_ptr->next_idx;
  400.         new_index->next_oid = prev_idx_ptr->next_oid;
  401.         prev_idx_ptr->next_idx = new_index;
  402.     } else {
  403.         if (res == 0 && idxptr) {
  404.             new_index->next_idx = idxptr;
  405.             new_index->next_oid = idxptr->next_oid;
  406.         } else {
  407.             new_index->next_idx = NULL;
  408.             new_index->next_oid = idxptr;
  409.         }
  410.         if (prev_oid_ptr) {
  411.             while (prev_oid_ptr) {
  412.                 prev_oid_ptr->next_oid = new_index;
  413.                 prev_oid_ptr = prev_oid_ptr->next_idx;
  414.             }
  415.         } else
  416.             snmp_index_head = new_index;
  417.     }
  418.     return rv;
  419. }
  420.         /*
  421.          * Release an allocated index,
  422.          *   to allow it to be used elsewhere
  423.          */
  424. int
  425. release_index(netsnmp_variable_list * varbind)
  426. {
  427.     return (unregister_index(varbind, TRUE, NULL));
  428. }
  429.         /*
  430.          * Completely remove an allocated index,
  431.          *   due to errors in the registration process.
  432.          */
  433. int
  434. remove_index(netsnmp_variable_list * varbind, netsnmp_session * ss)
  435. {
  436.     return (unregister_index(varbind, FALSE, ss));
  437. }
  438. void
  439. unregister_index_by_session(netsnmp_session * ss)
  440. {
  441.     struct snmp_index *idxptr, *idxptr2;
  442.     for (idxptr = snmp_index_head; idxptr != NULL;
  443.          idxptr = idxptr->next_oid)
  444.         for (idxptr2 = idxptr; idxptr2 != NULL;
  445.              idxptr2 = idxptr2->next_idx)
  446.             if (idxptr2->session == ss) {
  447.                 idxptr2->allocated = 0;
  448.                 idxptr2->session = NULL;
  449.             }
  450. }
  451. int
  452. unregister_index(netsnmp_variable_list * varbind, int remember,
  453.                  netsnmp_session * ss)
  454. {
  455.     struct snmp_index *idxptr, *idxptr2;
  456.     struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
  457.     int             res, res2, i;
  458. #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
  459.     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
  460.        NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
  461.         return (agentx_unregister_index(ss, varbind));
  462.     }
  463. #endif
  464.     /*
  465.      * Look for the requested OID entry 
  466.      */
  467.     prev_oid_ptr = NULL;
  468.     prev_idx_ptr = NULL;
  469.     res = 1;
  470.     res2 = 1;
  471.     for (idxptr = snmp_index_head; idxptr != NULL;
  472.          prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
  473.         if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
  474.                                     idxptr->varbind->name,
  475.                                     idxptr->varbind->name_length)) <= 0)
  476.             break;
  477.     }
  478.     if (res != 0)
  479.         return INDEX_ERR_NOT_ALLOCATED;
  480.     if (varbind->type != idxptr->varbind->type)
  481.         return INDEX_ERR_WRONG_TYPE;
  482.     for (idxptr2 = idxptr; idxptr2 != NULL;
  483.          prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
  484.         i = SNMP_MIN(varbind->val_len, idxptr2->varbind->val_len);
  485.         res2 =
  486.             memcmp(varbind->val.string, idxptr2->varbind->val.string, i);
  487.         if (res2 <= 0)
  488.             break;
  489.     }
  490.     if (res2 != 0 || (res2 == 0 && !idxptr2->allocated)) {
  491.         return INDEX_ERR_NOT_ALLOCATED;
  492.     }
  493.     if (ss != idxptr2->session)
  494.         return INDEX_ERR_WRONG_SESSION;
  495.     /*
  496.      *  If this is a "normal" index unregistration,
  497.      *      mark the index entry as unused, but leave
  498.      *      it in situ.  This allows differentiation
  499.      *      between ANY_INDEX and NEW_INDEX
  500.      */
  501.     if (remember) {
  502.         idxptr2->allocated = 0; /* Unused index */
  503.         idxptr2->session = NULL;
  504.         return SNMP_ERR_NOERROR;
  505.     }
  506.     /*
  507.      *  If this is a failed attempt to register a
  508.      *      number of indexes, the successful ones
  509.      *      must be removed completely.
  510.      */
  511.     if (prev_idx_ptr) {
  512.         prev_idx_ptr->next_idx = idxptr2->next_idx;
  513.     } else if (prev_oid_ptr) {
  514.         if (idxptr2->next_idx)  /* Use p_idx_ptr as a temp variable */
  515.             prev_idx_ptr = idxptr2->next_idx;
  516.         else
  517.             prev_idx_ptr = idxptr2->next_oid;
  518.         while (prev_oid_ptr) {
  519.             prev_oid_ptr->next_oid = prev_idx_ptr;
  520.             prev_oid_ptr = prev_oid_ptr->next_idx;
  521.         }
  522.     } else {
  523.         if (idxptr2->next_idx)
  524.             snmp_index_head = idxptr2->next_idx;
  525.         else
  526.             snmp_index_head = idxptr2->next_oid;
  527.     }
  528.     snmp_free_var(idxptr2->varbind);
  529.     free(idxptr2);
  530.     return SNMP_ERR_NOERROR;
  531. }
  532. int
  533. unregister_string_index(oid * name, size_t name_len, char *cp)
  534. {
  535.     netsnmp_variable_list varbind;
  536.     memset(&varbind, 0, sizeof(netsnmp_variable_list));
  537.     varbind.type = ASN_OCTET_STR;
  538.     snmp_set_var_objid(&varbind, name, name_len);
  539.     snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
  540.     return (unregister_index(&varbind, FALSE, main_session));
  541. }
  542. int
  543. unregister_int_index(oid * name, size_t name_len, int val)
  544. {
  545.     netsnmp_variable_list varbind;
  546.     memset(&varbind, 0, sizeof(netsnmp_variable_list));
  547.     varbind.type = ASN_INTEGER;
  548.     snmp_set_var_objid(&varbind, name, name_len);
  549.     varbind.val.string = varbind.buf;
  550.     varbind.val_len = sizeof(long);
  551.     *varbind.val.integer = val;
  552.     return (unregister_index(&varbind, FALSE, main_session));
  553. }
  554. int
  555. unregister_oid_index(oid * name, size_t name_len,
  556.                      oid * value, size_t value_len)
  557. {
  558.     netsnmp_variable_list varbind;
  559.     memset(&varbind, 0, sizeof(netsnmp_variable_list));
  560.     varbind.type = ASN_OBJECT_ID;
  561.     snmp_set_var_objid(&varbind, name, name_len);
  562.     snmp_set_var_value(&varbind, (u_char *) value,
  563.                        value_len * sizeof(oid));
  564.     return (unregister_index(&varbind, FALSE, main_session));
  565. }
  566. void
  567. dump_idx_registry(void)
  568. {
  569.     struct snmp_index *idxptr, *idxptr2;
  570.     u_char         *sbuf = NULL, *ebuf = NULL;
  571.     size_t          sbuf_len = 0, sout_len = 0, ebuf_len = 0, eout_len = 0;
  572.     if (snmp_index_head != NULL) {
  573.         printf("nIndex Allocations:n");
  574.     }
  575.     for (idxptr = snmp_index_head; idxptr != NULL;
  576.          idxptr = idxptr->next_oid) {
  577.         sout_len = 0;
  578.         if (sprint_realloc_objid(&sbuf, &sbuf_len, &sout_len, 1,
  579.                                  idxptr->varbind->name,
  580.                                  idxptr->varbind->name_length)) {
  581.             printf("%s indexes:n", sbuf);
  582.         } else {
  583.             printf("%s [TRUNCATED] indexes:n", sbuf);
  584.         }
  585.         for (idxptr2 = idxptr; idxptr2 != NULL;
  586.              idxptr2 = idxptr2->next_idx) {
  587.             switch (idxptr2->varbind->type) {
  588.             case ASN_INTEGER:
  589.                 printf("    %ld for session %8p, allocated %dn",
  590.                        *idxptr2->varbind->val.integer, idxptr2->session,
  591.                        idxptr2->allocated);
  592.                 break;
  593.             case ASN_OCTET_STR:
  594.                 printf("    "%s" for session %8p, allocated %dn",
  595.                        idxptr2->varbind->val.string, idxptr2->session,
  596.                        idxptr2->allocated);
  597.                 break;
  598.             case ASN_OBJECT_ID:
  599.                 eout_len = 0;
  600.                 if (sprint_realloc_objid(&ebuf, &ebuf_len, &eout_len, 1,
  601.                                          idxptr2->varbind->val.objid,
  602.                                          idxptr2->varbind->val_len /
  603.                                          sizeof(oid))) {
  604.                     printf("    %s for session %8p, allocated %dn", ebuf,
  605.                            idxptr2->session, idxptr2->allocated);
  606.                 } else {
  607.                     printf
  608.                         ("    %s [TRUNCATED] for sess %8p, allocated %dn",
  609.                          ebuf, idxptr2->session, idxptr2->allocated);
  610.                 }
  611.                 break;
  612.             default:
  613.                 printf("unsupported type (%d/0x%02x)n",
  614.                        idxptr2->varbind->type, idxptr2->varbind->type);
  615.             }
  616.         }
  617.     }
  618.     if (sbuf != NULL) {
  619.         free(sbuf);
  620.     }
  621.     if (ebuf != NULL) {
  622.         free(ebuf);
  623.     }
  624. }
  625. unsigned long
  626. count_indexes(oid * name, size_t namelen, int include_unallocated)
  627. {
  628.     struct snmp_index *i = NULL, *j = NULL;
  629.     unsigned long   n = 0;
  630.     for (i = snmp_index_head; i != NULL; i = i->next_oid) {
  631.         if (netsnmp_oid_equals(name, namelen,
  632.                              i->varbind->name,
  633.                              i->varbind->name_length) == 0) {
  634.             for (j = i; j != NULL; j = j->next_idx) {
  635.                 if (j->allocated || include_unallocated) {
  636.                     n++;
  637.                 }
  638.             }
  639.         }
  640.     }
  641.     return n;
  642. }
  643. #ifdef TESTING
  644. netsnmp_variable_list varbind;
  645. netsnmp_session main_sess, *main_session = &main_sess;
  646. void
  647. test_string_register(int n, char *cp)
  648. {
  649.     varbind->name[4] = n;
  650.     if (register_string_index(varbind->name, varbind.name_length, cp) ==
  651.         NULL)
  652.         printf("allocating %s failedn", cp);
  653. }
  654. void
  655. test_int_register(int n, int val)
  656. {
  657.     varbind->name[4] = n;
  658.     if (register_int_index(varbind->name, varbind.name_length, val) == -1)
  659.         printf("allocating %d/%d failedn", n, val);
  660. }
  661. void
  662. test_oid_register(int n, int subid)
  663. {
  664.     netsnmp_variable_list *res;
  665.     varbind->name[4] = n;
  666.     if (subid != -1) {
  667.         varbind->val.objid[5] = subid;
  668.         res = register_oid_index(varbind->name, varbind.name_length,
  669.                                  varbind->val.objid,
  670.                                  varbind->val_len / sizeof(oid));
  671.     } else
  672.         res =
  673.             register_oid_index(varbind->name, varbind.name_length, NULL,
  674.                                0);
  675.     if (res == NULL)
  676.         printf("allocating %d/%d failedn", n, subid);
  677. }
  678. void
  679. main(int argc, char argv[])
  680. {
  681.     oid             name[] = { 1, 2, 3, 4, 0 };
  682.     int             i;
  683.     memset(&varbind, 0, sizeof(netsnmp_variable_list));
  684.     snmp_set_var_objid(&varbind, name, 5);
  685.     varbind->type = ASN_OCTET_STR;
  686.     /*
  687.      * Test index structure linking:
  688.      *      a) sorted by OID
  689.      */
  690.     test_string_register(20, "empty OID");
  691.     test_string_register(10, "first OID");
  692.     test_string_register(40, "last OID");
  693.     test_string_register(30, "middle OID");
  694.     /*
  695.      *      b) sorted by index value
  696.      */
  697.     test_string_register(25, "eee: empty IDX");
  698.     test_string_register(25, "aaa: first IDX");
  699.     test_string_register(25, "zzz: last IDX");
  700.     test_string_register(25, "mmm: middle IDX");
  701.     printf("This next one should fail....n");
  702.     test_string_register(25, "eee: empty IDX"); /* duplicate */
  703.     printf("donen");
  704.     /*
  705.      *      c) test initial index linking
  706.      */
  707.     test_string_register(5, "eee: empty initial IDX");
  708.     test_string_register(5, "aaa: replace initial IDX");
  709.     /*
  710.      *      Did it all work?
  711.      */
  712.     dump_idx_registry();
  713.     unregister_index_by_session(main_session);
  714.     /*
  715.      *  Now test index allocation
  716.      *      a) integer values
  717.      */
  718.     test_int_register(110, -1); /* empty */
  719.     test_int_register(110, -1); /* append */
  720.     test_int_register(110, 10); /* append exact */
  721.     printf("This next one should fail....n");
  722.     test_int_register(110, 10); /* exact duplicate */
  723.     printf("donen");
  724.     test_int_register(110, -1); /* append */
  725.     test_int_register(110, 5);  /* insert exact */
  726.     /*
  727.      *      b) string values
  728.      */
  729.     test_string_register(120, NULL);    /* empty */
  730.     test_string_register(120, NULL);    /* append */
  731.     test_string_register(120, "aaaz");
  732.     test_string_register(120, NULL);    /* minor rollover */
  733.     test_string_register(120, "zzzz");
  734.     test_string_register(120, NULL);    /* major rollover */
  735.     /*
  736.      *      c) OID values
  737.      */
  738.     test_oid_register(130, -1); /* empty */
  739.     test_oid_register(130, -1); /* append */
  740.     varbind->val_len = varbind.name_length * sizeof(oid);
  741.     memcpy(varbind->buf, varbind.name, varbind.val_len);
  742.     varbind->val.objid = (oid *) varbind.buf;
  743.     varbind->val_len += sizeof(oid);
  744.     test_oid_register(130, 255);        /* append exact */
  745.     test_oid_register(130, -1); /* minor rollover */
  746.     test_oid_register(130, 100);        /* insert exact */
  747.     printf("This next one should fail....n");
  748.     test_oid_register(130, 100);        /* exact duplicate */
  749.     printf("donen");
  750.     varbind->val.objid = (oid *) varbind.buf;
  751.     for (i = 0; i < 6; i++)
  752.         varbind->val.objid[i] = 255;
  753.     varbind->val.objid[0] = 1;
  754.     test_oid_register(130, 255);        /* set up rollover  */
  755.     test_oid_register(130, -1); /* medium rollover */
  756.     for (i = 0; i < 6; i++)
  757.         varbind->val.objid[i] = 255;
  758.     varbind->val.objid[0] = 2;
  759.     test_oid_register(130, 255);        /* set up rollover  */
  760.     test_oid_register(130, -1); /* major rollover */
  761.     /*
  762.      *      Did it all work?
  763.      */
  764.     dump_idx_registry();
  765.     /*
  766.      *      Test the various "invalid" requests
  767.      *      (unsupported types, mis-matched types, etc)
  768.      */
  769.     printf("The rest of these should fail....n");
  770.     test_oid_register(110, -1);
  771.     test_oid_register(110, 100);
  772.     test_oid_register(120, -1);
  773.     test_oid_register(120, 100);
  774.     test_string_register(110, NULL);
  775.     test_string_register(110, "aaaa");
  776.     test_string_register(130, NULL);
  777.     test_string_register(130, "aaaa");
  778.     test_int_register(120, -1);
  779.     test_int_register(120, 1);
  780.     test_int_register(130, -1);
  781.     test_int_register(130, 1);
  782.     printf("done - this dump should be the same as beforen");
  783.     dump_idx_registry();
  784. }
  785. #endif