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 %8p\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 (NULL == 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
Last modified: Wednesday, 01-Aug-2018 04:41:28 UTC
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.