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