agent_index.c

00001 /*
00002  * agent_index.c
00003  *
00004  * Maintain a registry of index allocations
00005  *      (Primarily required for AgentX support,
00006  *       but it could be more widely useable).
00007  */
00008 
00009 
00010 #include <net-snmp/net-snmp-config.h>
00011 #include <signal.h>
00012 #if HAVE_STRING_H
00013 #include <string.h>
00014 #endif
00015 #if HAVE_STDLIB_H
00016 #include <stdlib.h>
00017 #endif
00018 #include <sys/types.h>
00019 #include <stdio.h>
00020 #include <fcntl.h>
00021 #if HAVE_WINSOCK_H
00022 #include <winsock.h>
00023 #endif
00024 #if TIME_WITH_SYS_TIME
00025 # ifdef WIN32
00026 #  include <sys/timeb.h>
00027 # else
00028 #  include <sys/time.h>
00029 # endif
00030 # include <time.h>
00031 #else
00032 # if HAVE_SYS_TIME_H
00033 #  include <sys/time.h>
00034 # else
00035 #  include <time.h>
00036 # endif
00037 #endif
00038 #if HAVE_NETINET_IN_H
00039 #include <netinet/in.h>
00040 #endif
00041 
00042 #include <net-snmp/net-snmp-includes.h>
00043 #include <net-snmp/agent/net-snmp-agent-includes.h>
00044 #include <net-snmp/agent/agent_callbacks.h>
00045 #include <net-snmp/agent/agent_index.h>
00046 
00047 #include "snmpd.h"
00048 #include "mibgroup/struct.h"
00049 #include <net-snmp/agent/table.h>
00050 #include <net-snmp/agent/table_iterator.h>
00051 #include "mib_module_includes.h"
00052 
00053 #ifdef USING_AGENTX_SUBAGENT_MODULE
00054 #include "agentx/subagent.h"
00055 #include "agentx/client.h"
00056 #endif
00057 
00058         /*
00059          * Initial support for index allocation
00060          */
00061 
00062 struct snmp_index {
00063     netsnmp_variable_list *varbind;     /* or pointer to var_list ? */
00064     int             allocated;
00065     netsnmp_session *session;
00066     struct snmp_index *next_oid;
00067     struct snmp_index *prev_oid;
00068     struct snmp_index *next_idx;
00069 }              *snmp_index_head = NULL;
00070 
00071 extern netsnmp_session *main_session;
00072 
00073 /*
00074  * The caller is responsible for free()ing the memory returned by
00075  * this function.  
00076  */
00077 
00078 char           *
00079 register_string_index(oid * name, size_t name_len, char *cp)
00080 {
00081     netsnmp_variable_list varbind, *res;
00082 
00083     memset(&varbind, 0, sizeof(netsnmp_variable_list));
00084     varbind.type = ASN_OCTET_STR;
00085     snmp_set_var_objid(&varbind, name, name_len);
00086     if (cp != ANY_STRING_INDEX) {
00087         snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
00088         res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
00089     } else {
00090         res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
00091     }
00092 
00093     if (res == NULL) {
00094         return NULL;
00095     } else {
00096         char           *rv = strdup(res->val.string);
00097         free(res);
00098         return rv;
00099     }
00100 }
00101 
00102 int
00103 register_int_index(oid * name, size_t name_len, int val)
00104 {
00105     netsnmp_variable_list varbind, *res;
00106 
00107     memset(&varbind, 0, sizeof(netsnmp_variable_list));
00108     varbind.type = ASN_INTEGER;
00109     snmp_set_var_objid(&varbind, name, name_len);
00110     varbind.val.string = varbind.buf;
00111     if (val != ANY_INTEGER_INDEX) {
00112         varbind.val_len = sizeof(long);
00113         *varbind.val.integer = val;
00114         res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
00115     } else {
00116         res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
00117     }
00118 
00119     if (res == NULL) {
00120         return -1;
00121     } else {
00122         int             rv = *(res->val.integer);
00123         free(res);
00124         return rv;
00125     }
00126 }
00127 
00128 /*
00129  * The caller is responsible for free()ing the memory returned by
00130  * this function.  
00131  */
00132 
00133 netsnmp_variable_list *
00134 register_oid_index(oid * name, size_t name_len,
00135                    oid * value, size_t value_len)
00136 {
00137     netsnmp_variable_list varbind;
00138 
00139     memset(&varbind, 0, sizeof(netsnmp_variable_list));
00140     varbind.type = ASN_OBJECT_ID;
00141     snmp_set_var_objid(&varbind, name, name_len);
00142     if (value != ANY_OID_INDEX) {
00143         snmp_set_var_value(&varbind, (u_char *) value,
00144                            value_len * sizeof(oid));
00145         return register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
00146     } else {
00147         return register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
00148     }
00149 }
00150 
00151 /*
00152  * The caller is responsible for free()ing the memory returned by
00153  * this function.  
00154  */
00155 
00156 netsnmp_variable_list *
00157 register_index(netsnmp_variable_list * varbind, int flags,
00158                netsnmp_session * ss)
00159 {
00160     netsnmp_variable_list *rv = NULL;
00161     struct snmp_index *new_index, *idxptr, *idxptr2;
00162     struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
00163     int             res, res2, i;
00164 
00165     DEBUGMSGTL(("register_index", "register "));
00166     DEBUGMSGVAR(("register_index", varbind));
00167     DEBUGMSG(("register_index", "for session %08p\n", ss));
00168 
00169 #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
00170     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
00171                                NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
00172         return (agentx_register_index(ss, varbind, flags));
00173     }
00174 #endif
00175     /*
00176      * Look for the requested OID entry 
00177      */
00178     prev_oid_ptr = NULL;
00179     prev_idx_ptr = NULL;
00180     res = 1;
00181     res2 = 1;
00182     for (idxptr = snmp_index_head; idxptr != NULL;
00183          prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
00184         if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
00185                                     idxptr->varbind->name,
00186                                     idxptr->varbind->name_length)) <= 0)
00187             break;
00188     }
00189 
00190     /*
00191      * Found the OID - now look at the registered indices 
00192      */
00193     if (res == 0 && idxptr) {
00194         if (varbind->type != idxptr->varbind->type)
00195             return NULL;        /* wrong type */
00196 
00197         /*
00198          * If we've been asked for an arbitrary new value,
00199          *      then find the end of the list.
00200          * If we've been asked for any arbitrary value,
00201          *      then look for an unused entry, and use that.
00202          *      If there aren't any, continue as for new.
00203          * Otherwise, locate the given value in the (sorted)
00204          *      list of already allocated values
00205          */
00206         if (flags & ALLOCATE_ANY_INDEX) {
00207             for (idxptr2 = idxptr; idxptr2 != NULL;
00208                  prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
00209 
00210                 if (flags == ALLOCATE_ANY_INDEX && !(idxptr2->allocated)) {
00211                     if ((rv =
00212                          snmp_clone_varbind(idxptr2->varbind)) != NULL) {
00213                         idxptr2->session = ss;
00214                         idxptr2->allocated = 1;
00215                     }
00216                     return rv;
00217                 }
00218             }
00219         } else {
00220             for (idxptr2 = idxptr; idxptr2 != NULL;
00221                  prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
00222                 switch (varbind->type) {
00223                 case ASN_INTEGER:
00224                     res2 =
00225                         (*varbind->val.integer -
00226                          *idxptr2->varbind->val.integer);
00227                     break;
00228                 case ASN_OCTET_STR:
00229                     i = SNMP_MIN(varbind->val_len,
00230                                  idxptr2->varbind->val_len);
00231                     res2 =
00232                         memcmp(varbind->val.string,
00233                                idxptr2->varbind->val.string, i);
00234                     break;
00235                 case ASN_OBJECT_ID:
00236                     res2 =
00237                         snmp_oid_compare(varbind->val.objid,
00238                                          varbind->val_len / sizeof(oid),
00239                                          idxptr2->varbind->val.objid,
00240                                          idxptr2->varbind->val_len /
00241                                          sizeof(oid));
00242                     break;
00243                 default:
00244                     return NULL;        /* wrong type */
00245                 }
00246                 if (res2 <= 0)
00247                     break;
00248             }
00249             if (res2 == 0) {
00250                 if (idxptr2->allocated) {
00251                     /*
00252                      * No good: the index is in use.  
00253                      */
00254                     return NULL;
00255                 } else {
00256                     /*
00257                      * Okay, it's unallocated, we can just claim ownership
00258                      * here.  
00259                      */
00260                     if ((rv =
00261                          snmp_clone_varbind(idxptr2->varbind)) != NULL) {
00262                         idxptr2->session = ss;
00263                         idxptr2->allocated = 1;
00264                     }
00265                     return rv;
00266                 }
00267             }
00268         }
00269     }
00270 
00271     /*
00272      * OK - we've now located where the new entry needs to
00273      *      be fitted into the index registry tree          
00274      * To recap:
00275      *      'prev_oid_ptr' points to the head of the OID index
00276      *          list prior to this one.  If this is null, then
00277      *          it means that this is the first OID in the list.
00278      *      'idxptr' points either to the head of this OID list,
00279      *          or the next OID (if this is a new OID request)
00280      *          These can be distinguished by the value of 'res'.
00281      *
00282      *      'prev_idx_ptr' points to the index entry that sorts
00283      *          immediately prior to the requested value (if any).
00284      *          If an arbitrary value is required, then this will
00285      *          point to the last allocated index.
00286      *          If this pointer is null, then either this is a new
00287      *          OID request, or the requested value is the first
00288      *          in the list.
00289      *      'idxptr2' points to the next sorted index (if any)
00290      *          but is not actually needed any more.
00291      *
00292      *  Clear?  Good!
00293      *      I hope you've been paying attention.
00294      *          There'll be a test later :-)
00295      */
00296 
00297     /*
00298      *      We proceed by creating the new entry
00299      *         (by copying the entry provided)
00300      */
00301     new_index = (struct snmp_index *) calloc(1, sizeof(struct snmp_index));
00302     if (new_index == NULL)
00303         return NULL;
00304 
00305     if (0 == snmp_varlist_add_variable(&new_index->varbind,
00306                                        varbind->name,
00307                                        varbind->name_length,
00308                                        varbind->type,
00309                                        varbind->val.string,
00310                                        varbind->val_len)) {
00311         /*
00312          * if (snmp_clone_var( varbind, new_index->varbind ) != 0 ) 
00313          */
00314         free(new_index);
00315         return NULL;
00316     }
00317     new_index->session = ss;
00318     new_index->allocated = 1;
00319 
00320     if (varbind->type == ASN_OCTET_STR && flags == ALLOCATE_THIS_INDEX)
00321         new_index->varbind->val.string[new_index->varbind->val_len] = 0;
00322 
00323     /*
00324      * If we've been given a value, then we can use that, but
00325      *    otherwise, we need to create a new value for this entry.
00326      * Note that ANY_INDEX and NEW_INDEX are both covered by this
00327      *   test (since NEW_INDEX & ANY_INDEX = ANY_INDEX, remember?)
00328      */
00329     if (flags & ALLOCATE_ANY_INDEX) {
00330         if (prev_idx_ptr) {
00331             if (snmp_clone_var(prev_idx_ptr->varbind, new_index->varbind)
00332                 != 0) {
00333                 free(new_index);
00334                 return NULL;
00335             }
00336         } else
00337             new_index->varbind->val.string = new_index->varbind->buf;
00338 
00339         switch (varbind->type) {
00340         case ASN_INTEGER:
00341             if (prev_idx_ptr) {
00342                 (*new_index->varbind->val.integer)++;
00343             } else
00344                 *(new_index->varbind->val.integer) = 1;
00345             new_index->varbind->val_len = sizeof(long);
00346             break;
00347         case ASN_OCTET_STR:
00348             if (prev_idx_ptr) {
00349                 i = new_index->varbind->val_len - 1;
00350                 while (new_index->varbind->buf[i] == 'z') {
00351                     new_index->varbind->buf[i] = 'a';
00352                     i--;
00353                     if (i < 0) {
00354                         i = new_index->varbind->val_len;
00355                         new_index->varbind->buf[i] = 'a';
00356                         new_index->varbind->buf[i + 1] = 0;
00357                     }
00358                 }
00359                 new_index->varbind->buf[i]++;
00360             } else
00361                 strcpy((char *) new_index->varbind->buf, "aaaa");
00362             new_index->varbind->val_len =
00363                 strlen((char *) new_index->varbind->buf);
00364             break;
00365         case ASN_OBJECT_ID:
00366             if (prev_idx_ptr) {
00367                 i = prev_idx_ptr->varbind->val_len / sizeof(oid) - 1;
00368                 while (new_index->varbind->val.objid[i] == 255) {
00369                     new_index->varbind->val.objid[i] = 1;
00370                     i--;
00371                     if (i == 0 && new_index->varbind->val.objid[0] == 2) {
00372                         new_index->varbind->val.objid[0] = 1;
00373                         i = new_index->varbind->val_len / sizeof(oid);
00374                         new_index->varbind->val.objid[i] = 0;
00375                         new_index->varbind->val_len += sizeof(oid);
00376                     }
00377                 }
00378                 new_index->varbind->val.objid[i]++;
00379             } else {
00380                 /*
00381                  * If the requested OID name is small enough,
00382                  * *   append another OID (1) and use this as the
00383                  * *   default starting value for new indexes.
00384                  */
00385                 if ((varbind->name_length + 1) * sizeof(oid) <= 40) {
00386                     for (i = 0; i < (int) varbind->name_length; i++)
00387                         new_index->varbind->val.objid[i] =
00388                             varbind->name[i];
00389                     new_index->varbind->val.objid[varbind->name_length] =
00390                         1;
00391                     new_index->varbind->val_len =
00392                         (varbind->name_length + 1) * sizeof(oid);
00393                 } else {
00394                     /*
00395                      * Otherwise use '.1.1.1.1...' 
00396                      */
00397                     i = 40 / sizeof(oid);
00398                     if (i > 4)
00399                         i = 4;
00400                     new_index->varbind->val_len = i * (sizeof(oid));
00401                     for (i--; i >= 0; i--)
00402                         new_index->varbind->val.objid[i] = 1;
00403                 }
00404             }
00405             break;
00406         default:
00407             snmp_free_var(new_index->varbind);
00408             free(new_index);
00409             return NULL;        /* Index type not supported */
00410         }
00411     }
00412 
00413     /*
00414      * Try to duplicate the new varbind for return.  
00415      */
00416 
00417     if ((rv = snmp_clone_varbind(new_index->varbind)) == NULL) {
00418         snmp_free_var(new_index->varbind);
00419         free(new_index);
00420         return NULL;
00421     }
00422 
00423     /*
00424      * Right - we've set up the new entry.
00425      * All that remains is to link it into the tree.
00426      * There are a number of possible cases here,
00427      *   so watch carefully.
00428      */
00429     if (prev_idx_ptr) {
00430         new_index->next_idx = prev_idx_ptr->next_idx;
00431         new_index->next_oid = prev_idx_ptr->next_oid;
00432         prev_idx_ptr->next_idx = new_index;
00433     } else {
00434         if (res == 0 && idxptr) {
00435             new_index->next_idx = idxptr;
00436             new_index->next_oid = idxptr->next_oid;
00437         } else {
00438             new_index->next_idx = NULL;
00439             new_index->next_oid = idxptr;
00440         }
00441 
00442         if (prev_oid_ptr) {
00443             while (prev_oid_ptr) {
00444                 prev_oid_ptr->next_oid = new_index;
00445                 prev_oid_ptr = prev_oid_ptr->next_idx;
00446             }
00447         } else
00448             snmp_index_head = new_index;
00449     }
00450     return rv;
00451 }
00452 
00453         /*
00454          * Release an allocated index,
00455          *   to allow it to be used elsewhere
00456          */
00457 int
00458 release_index(netsnmp_variable_list * varbind)
00459 {
00460     return (unregister_index(varbind, TRUE, NULL));
00461 }
00462 
00463         /*
00464          * Completely remove an allocated index,
00465          *   due to errors in the registration process.
00466          */
00467 int
00468 remove_index(netsnmp_variable_list * varbind, netsnmp_session * ss)
00469 {
00470     return (unregister_index(varbind, FALSE, ss));
00471 }
00472 
00473 void
00474 unregister_index_by_session(netsnmp_session * ss)
00475 {
00476     struct snmp_index *idxptr, *idxptr2;
00477     for (idxptr = snmp_index_head; idxptr != NULL;
00478          idxptr = idxptr->next_oid)
00479         for (idxptr2 = idxptr; idxptr2 != NULL;
00480              idxptr2 = idxptr2->next_idx)
00481             if (idxptr2->session == ss) {
00482                 idxptr2->allocated = 0;
00483                 idxptr2->session = NULL;
00484             }
00485 }
00486 
00487 
00488 int
00489 unregister_index(netsnmp_variable_list * varbind, int remember,
00490                  netsnmp_session * ss)
00491 {
00492     struct snmp_index *idxptr, *idxptr2;
00493     struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
00494     int             res, res2, i;
00495 
00496 #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
00497     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
00498                                NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
00499         return (agentx_unregister_index(ss, varbind));
00500     }
00501 #endif
00502     /*
00503      * Look for the requested OID entry 
00504      */
00505     prev_oid_ptr = NULL;
00506     prev_idx_ptr = NULL;
00507     res = 1;
00508     res2 = 1;
00509     for (idxptr = snmp_index_head; idxptr != NULL;
00510          prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
00511         if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
00512                                     idxptr->varbind->name,
00513                                     idxptr->varbind->name_length)) <= 0)
00514             break;
00515     }
00516 
00517     if (res != 0)
00518         return INDEX_ERR_NOT_ALLOCATED;
00519     if (varbind->type != idxptr->varbind->type)
00520         return INDEX_ERR_WRONG_TYPE;
00521 
00522     for (idxptr2 = idxptr; idxptr2 != NULL;
00523          prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
00524         i = SNMP_MIN(varbind->val_len, idxptr2->varbind->val_len);
00525         res2 =
00526             memcmp(varbind->val.string, idxptr2->varbind->val.string, i);
00527         if (res2 <= 0)
00528             break;
00529     }
00530     if (res2 != 0 || (res2 == 0 && !idxptr2->allocated)) {
00531         return INDEX_ERR_NOT_ALLOCATED;
00532     }
00533     if (ss != idxptr2->session)
00534         return INDEX_ERR_WRONG_SESSION;
00535 
00536     /*
00537      *  If this is a "normal" index unregistration,
00538      *      mark the index entry as unused, but leave
00539      *      it in situ.  This allows differentiation
00540      *      between ANY_INDEX and NEW_INDEX
00541      */
00542     if (remember) {
00543         idxptr2->allocated = 0; /* Unused index */
00544         idxptr2->session = NULL;
00545         return SNMP_ERR_NOERROR;
00546     }
00547     /*
00548      *  If this is a failed attempt to register a
00549      *      number of indexes, the successful ones
00550      *      must be removed completely.
00551      */
00552     if (prev_idx_ptr) {
00553         prev_idx_ptr->next_idx = idxptr2->next_idx;
00554     } else if (prev_oid_ptr) {
00555         if (idxptr2->next_idx)  /* Use p_idx_ptr as a temp variable */
00556             prev_idx_ptr = idxptr2->next_idx;
00557         else
00558             prev_idx_ptr = idxptr2->next_oid;
00559         while (prev_oid_ptr) {
00560             prev_oid_ptr->next_oid = prev_idx_ptr;
00561             prev_oid_ptr = prev_oid_ptr->next_idx;
00562         }
00563     } else {
00564         if (idxptr2->next_idx)
00565             snmp_index_head = idxptr2->next_idx;
00566         else
00567             snmp_index_head = idxptr2->next_oid;
00568     }
00569     snmp_free_var(idxptr2->varbind);
00570     free(idxptr2);
00571     return SNMP_ERR_NOERROR;
00572 }
00573 
00574 int
00575 unregister_string_index(oid * name, size_t name_len, char *cp)
00576 {
00577     netsnmp_variable_list varbind;
00578 
00579     memset(&varbind, 0, sizeof(netsnmp_variable_list));
00580     varbind.type = ASN_OCTET_STR;
00581     snmp_set_var_objid(&varbind, name, name_len);
00582     snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
00583     return (unregister_index(&varbind, FALSE, main_session));
00584 }
00585 
00586 int
00587 unregister_int_index(oid * name, size_t name_len, int val)
00588 {
00589     netsnmp_variable_list varbind;
00590 
00591     memset(&varbind, 0, sizeof(netsnmp_variable_list));
00592     varbind.type = ASN_INTEGER;
00593     snmp_set_var_objid(&varbind, name, name_len);
00594     varbind.val.string = varbind.buf;
00595     varbind.val_len = sizeof(long);
00596     *varbind.val.integer = val;
00597     return (unregister_index(&varbind, FALSE, main_session));
00598 }
00599 
00600 int
00601 unregister_oid_index(oid * name, size_t name_len,
00602                      oid * value, size_t value_len)
00603 {
00604     netsnmp_variable_list varbind;
00605 
00606     memset(&varbind, 0, sizeof(netsnmp_variable_list));
00607     varbind.type = ASN_OBJECT_ID;
00608     snmp_set_var_objid(&varbind, name, name_len);
00609     snmp_set_var_value(&varbind, (u_char *) value,
00610                        value_len * sizeof(oid));
00611     return (unregister_index(&varbind, FALSE, main_session));
00612 }
00613 
00614 void
00615 dump_idx_registry(void)
00616 {
00617     struct snmp_index *idxptr, *idxptr2;
00618     u_char         *sbuf = NULL, *ebuf = NULL;
00619     size_t          sbuf_len = 0, sout_len = 0, ebuf_len = 0, eout_len = 0;
00620 
00621     if (snmp_index_head != NULL) {
00622         printf("\nIndex Allocations:\n");
00623     }
00624 
00625     for (idxptr = snmp_index_head; idxptr != NULL;
00626          idxptr = idxptr->next_oid) {
00627         sout_len = 0;
00628         if (sprint_realloc_objid(&sbuf, &sbuf_len, &sout_len, 1,
00629                                  idxptr->varbind->name,
00630                                  idxptr->varbind->name_length)) {
00631             printf("%s indexes:\n", sbuf);
00632         } else {
00633             printf("%s [TRUNCATED] indexes:\n", sbuf);
00634         }
00635 
00636         for (idxptr2 = idxptr; idxptr2 != NULL;
00637              idxptr2 = idxptr2->next_idx) {
00638             switch (idxptr2->varbind->type) {
00639             case ASN_INTEGER:
00640                 printf("    %ld for session %8p, allocated %d\n",
00641                        *idxptr2->varbind->val.integer, idxptr2->session,
00642                        idxptr2->allocated);
00643                 break;
00644             case ASN_OCTET_STR:
00645                 printf("    \"%s\" for session %8p, allocated %d\n",
00646                        idxptr2->varbind->val.string, idxptr2->session,
00647                        idxptr2->allocated);
00648                 break;
00649             case ASN_OBJECT_ID:
00650                 eout_len = 0;
00651                 if (sprint_realloc_objid(&ebuf, &ebuf_len, &eout_len, 1,
00652                                          idxptr2->varbind->val.objid,
00653                                          idxptr2->varbind->val_len /
00654                                          sizeof(oid))) {
00655                     printf("    %s for session %8p, allocated %d\n", ebuf,
00656                            idxptr2->session, idxptr2->allocated);
00657                 } else {
00658                     printf
00659                         ("    %s [TRUNCATED] for sess %8p, allocated %d\n",
00660                          ebuf, idxptr2->session, idxptr2->allocated);
00661                 }
00662                 break;
00663             default:
00664                 printf("unsupported type (%d/0x%02x)\n",
00665                        idxptr2->varbind->type, idxptr2->varbind->type);
00666             }
00667         }
00668     }
00669 
00670     if (sbuf != NULL) {
00671         free(sbuf);
00672     }
00673     if (ebuf != NULL) {
00674         free(ebuf);
00675     }
00676 }
00677 
00678 unsigned long
00679 count_indexes(oid * name, size_t namelen, int include_unallocated)
00680 {
00681     struct snmp_index *i = NULL, *j = NULL;
00682     unsigned long   n = 0;
00683 
00684     for (i = snmp_index_head; i != NULL; i = i->next_oid) {
00685         if (netsnmp_oid_equals(name, namelen,
00686                              i->varbind->name,
00687                              i->varbind->name_length) == 0) {
00688             for (j = i; j != NULL; j = j->next_idx) {
00689                 if (j->allocated || include_unallocated) {
00690                     n++;
00691                 }
00692             }
00693         }
00694     }
00695     return n;
00696 }
00697 
00698 
00699 #ifdef TESTING
00700 netsnmp_variable_list varbind;
00701 netsnmp_session main_sess, *main_session = &main_sess;
00702 
00703 void
00704 test_string_register(int n, char *cp)
00705 {
00706     varbind->name[4] = n;
00707     if (register_string_index(varbind->name, varbind.name_length, cp) ==
00708         NULL)
00709         printf("allocating %s failed\n", cp);
00710 }
00711 
00712 void
00713 test_int_register(int n, int val)
00714 {
00715     varbind->name[4] = n;
00716     if (register_int_index(varbind->name, varbind.name_length, val) == -1)
00717         printf("allocating %d/%d failed\n", n, val);
00718 }
00719 
00720 void
00721 test_oid_register(int n, int subid)
00722 {
00723     netsnmp_variable_list *res;
00724 
00725     varbind->name[4] = n;
00726     if (subid != -1) {
00727         varbind->val.objid[5] = subid;
00728         res = register_oid_index(varbind->name, varbind.name_length,
00729                                  varbind->val.objid,
00730                                  varbind->val_len / sizeof(oid));
00731     } else
00732         res =
00733             register_oid_index(varbind->name, varbind.name_length, NULL,
00734                                0);
00735 
00736     if (res == NULL)
00737         printf("allocating %d/%d failed\n", n, subid);
00738 }
00739 
00740 void
00741 main(int argc, char argv[])
00742 {
00743     oid             name[] = { 1, 2, 3, 4, 0 };
00744     int             i;
00745 
00746     memset(&varbind, 0, sizeof(netsnmp_variable_list));
00747     snmp_set_var_objid(&varbind, name, 5);
00748     varbind->type = ASN_OCTET_STR;
00749     /*
00750      * Test index structure linking:
00751      *      a) sorted by OID
00752      */
00753     test_string_register(20, "empty OID");
00754     test_string_register(10, "first OID");
00755     test_string_register(40, "last OID");
00756     test_string_register(30, "middle OID");
00757 
00758     /*
00759      *      b) sorted by index value
00760      */
00761     test_string_register(25, "eee: empty IDX");
00762     test_string_register(25, "aaa: first IDX");
00763     test_string_register(25, "zzz: last IDX");
00764     test_string_register(25, "mmm: middle IDX");
00765     printf("This next one should fail....\n");
00766     test_string_register(25, "eee: empty IDX"); /* duplicate */
00767     printf("done\n");
00768 
00769     /*
00770      *      c) test initial index linking
00771      */
00772     test_string_register(5, "eee: empty initial IDX");
00773     test_string_register(5, "aaa: replace initial IDX");
00774 
00775     /*
00776      *      Did it all work?
00777      */
00778     dump_idx_registry();
00779     unregister_index_by_session(main_session);
00780     /*
00781      *  Now test index allocation
00782      *      a) integer values
00783      */
00784     test_int_register(110, -1); /* empty */
00785     test_int_register(110, -1); /* append */
00786     test_int_register(110, 10); /* append exact */
00787     printf("This next one should fail....\n");
00788     test_int_register(110, 10); /* exact duplicate */
00789     printf("done\n");
00790     test_int_register(110, -1); /* append */
00791     test_int_register(110, 5);  /* insert exact */
00792 
00793     /*
00794      *      b) string values
00795      */
00796     test_string_register(120, NULL);    /* empty */
00797     test_string_register(120, NULL);    /* append */
00798     test_string_register(120, "aaaz");
00799     test_string_register(120, NULL);    /* minor rollover */
00800     test_string_register(120, "zzzz");
00801     test_string_register(120, NULL);    /* major rollover */
00802 
00803     /*
00804      *      c) OID values
00805      */
00806 
00807     test_oid_register(130, -1); /* empty */
00808     test_oid_register(130, -1); /* append */
00809 
00810     varbind->val_len = varbind.name_length * sizeof(oid);
00811     memcpy(varbind->buf, varbind.name, varbind.val_len);
00812     varbind->val.objid = (oid *) varbind.buf;
00813     varbind->val_len += sizeof(oid);
00814 
00815     test_oid_register(130, 255);        /* append exact */
00816     test_oid_register(130, -1); /* minor rollover */
00817     test_oid_register(130, 100);        /* insert exact */
00818     printf("This next one should fail....\n");
00819     test_oid_register(130, 100);        /* exact duplicate */
00820     printf("done\n");
00821 
00822     varbind->val.objid = (oid *) varbind.buf;
00823     for (i = 0; i < 6; i++)
00824         varbind->val.objid[i] = 255;
00825     varbind->val.objid[0] = 1;
00826     test_oid_register(130, 255);        /* set up rollover  */
00827     test_oid_register(130, -1); /* medium rollover */
00828 
00829     for (i = 0; i < 6; i++)
00830         varbind->val.objid[i] = 255;
00831     varbind->val.objid[0] = 2;
00832     test_oid_register(130, 255);        /* set up rollover  */
00833     test_oid_register(130, -1); /* major rollover */
00834 
00835     /*
00836      *      Did it all work?
00837      */
00838     dump_idx_registry();
00839 
00840     /*
00841      *      Test the various "invalid" requests
00842      *      (unsupported types, mis-matched types, etc)
00843      */
00844     printf("The rest of these should fail....\n");
00845     test_oid_register(110, -1);
00846     test_oid_register(110, 100);
00847     test_oid_register(120, -1);
00848     test_oid_register(120, 100);
00849     test_string_register(110, NULL);
00850     test_string_register(110, "aaaa");
00851     test_string_register(130, NULL);
00852     test_string_register(130, "aaaa");
00853     test_int_register(120, -1);
00854     test_int_register(120, 1);
00855     test_int_register(130, -1);
00856     test_int_register(130, 1);
00857     printf("done - this dump should be the same as before\n");
00858     dump_idx_registry();
00859 }
00860 #endif

net-snmpに対してSat Sep 5 13:14:19 2009に生成されました。  doxygen 1.4.7