net-snmp 5.7
|
00001 #include <net-snmp/net-snmp-config.h> 00002 00003 #include <string.h> 00004 00005 #include <stdlib.h> 00006 #include <sys/types.h> 00007 00008 #include <net-snmp/net-snmp-features.h> 00009 #include <net-snmp/net-snmp-includes.h> 00010 00011 netsnmp_feature_child_of(oid_stash_all, libnetsnmp) 00012 netsnmp_feature_child_of(oid_stash, oid_stash_all) 00013 netsnmp_feature_child_of(oid_stash_no_free, oid_stash_all) 00014 00015 #ifndef NETSNMP_FEATURE_REMOVE_OID_STASH 00016 00025 /* 00026 * xxx-rks: when you have some spare time: 00027 * 00028 * b) basically, everything currently creates one node per sub-oid, 00029 * which is less than optimal. add code to create nodes with the 00030 * longest possible OID per node, and split nodes when necessary 00031 * during adds. 00032 * 00033 * c) If you are feeling really ambitious, also merge split nodes if 00034 * possible on a delete. 00035 * 00036 * xxx-wes: uh, right, like I *ever* have that much time. 00037 * 00038 */ 00039 00040 /*************************************************************************** 00041 * 00042 * 00043 ***************************************************************************/ 00044 00052 netsnmp_oid_stash_node * 00053 netsnmp_oid_stash_create_sized_node(size_t mysize) 00054 { 00055 netsnmp_oid_stash_node *ret; 00056 ret = SNMP_MALLOC_TYPEDEF(netsnmp_oid_stash_node); 00057 if (!ret) 00058 return NULL; 00059 ret->children = (netsnmp_oid_stash_node**) calloc(mysize, sizeof(netsnmp_oid_stash_node *)); 00060 if (!ret->children) { 00061 free(ret); 00062 return NULL; 00063 } 00064 ret->children_size = mysize; 00065 return ret; 00066 } 00067 00072 NETSNMP_INLINE netsnmp_oid_stash_node * 00073 netsnmp_oid_stash_create_node(void) 00074 { 00075 return netsnmp_oid_stash_create_sized_node(OID_STASH_CHILDREN_SIZE); 00076 } 00077 00078 netsnmp_feature_child_of(oid_stash_add_data, oid_stash_all) 00079 #ifndef NETSNMP_FEATURE_REMOVE_OID_STASH_ADD_DATA 00080 00091 int 00092 netsnmp_oid_stash_add_data(netsnmp_oid_stash_node **root, 00093 const oid * lookup, size_t lookup_len, void *mydata) 00094 { 00095 netsnmp_oid_stash_node *curnode, *tmpp, *loopp; 00096 unsigned int i; 00097 00098 if (!root || !lookup || lookup_len == 0) 00099 return SNMPERR_GENERR; 00100 00101 if (!*root) { 00102 *root = netsnmp_oid_stash_create_node(); 00103 if (!*root) 00104 return SNMPERR_MALLOC; 00105 } 00106 DEBUGMSGTL(( "oid_stash", "stash_add_data ")); 00107 DEBUGMSGOID(("oid_stash", lookup, lookup_len)); 00108 DEBUGMSG(( "oid_stash", "\n")); 00109 tmpp = NULL; 00110 for (curnode = *root, i = 0; i < lookup_len; i++) { 00111 tmpp = curnode->children[lookup[i] % curnode->children_size]; 00112 if (!tmpp) { 00113 /* 00114 * no child in array at all 00115 */ 00116 tmpp = curnode->children[lookup[i] % curnode->children_size] = 00117 netsnmp_oid_stash_create_node(); 00118 tmpp->value = lookup[i]; 00119 tmpp->parent = curnode; 00120 } else { 00121 for (loopp = tmpp; loopp; loopp = loopp->next_sibling) { 00122 if (loopp->value == lookup[i]) 00123 break; 00124 } 00125 if (loopp) { 00126 tmpp = loopp; 00127 } else { 00128 /* 00129 * none exists. Create it 00130 */ 00131 loopp = netsnmp_oid_stash_create_node(); 00132 loopp->value = lookup[i]; 00133 loopp->next_sibling = tmpp; 00134 loopp->parent = curnode; 00135 tmpp->prev_sibling = loopp; 00136 curnode->children[lookup[i] % curnode->children_size] = 00137 loopp; 00138 tmpp = loopp; 00139 } 00140 /* 00141 * tmpp now points to the proper node 00142 */ 00143 } 00144 curnode = tmpp; 00145 } 00146 /* 00147 * tmpp now points to the exact match 00148 */ 00149 if (curnode->thedata) 00150 return SNMPERR_GENERR; 00151 if (NULL == tmpp) 00152 return SNMPERR_GENERR; 00153 tmpp->thedata = mydata; 00154 return SNMPERR_SUCCESS; 00155 } 00156 #endif /* NETSNMP_FEATURE_REMOVE_OID_STASH_ADD_DATA */ 00157 00163 netsnmp_oid_stash_node * 00164 netsnmp_oid_stash_get_node(netsnmp_oid_stash_node *root, 00165 const oid * lookup, size_t lookup_len) 00166 { 00167 netsnmp_oid_stash_node *curnode, *tmpp, *loopp; 00168 unsigned int i; 00169 00170 if (!root) 00171 return NULL; 00172 tmpp = NULL; 00173 for (curnode = root, i = 0; i < lookup_len; i++) { 00174 tmpp = curnode->children[lookup[i] % curnode->children_size]; 00175 if (!tmpp) { 00176 return NULL; 00177 } else { 00178 for (loopp = tmpp; loopp; loopp = loopp->next_sibling) { 00179 if (loopp->value == lookup[i]) 00180 break; 00181 } 00182 if (loopp) { 00183 tmpp = loopp; 00184 } else { 00185 return NULL; 00186 } 00187 } 00188 curnode = tmpp; 00189 } 00190 return tmpp; 00191 } 00192 00200 netsnmp_feature_child_of(oid_stash_iterate, oid_stash_all) 00201 #ifndef NETSNMP_FEATURE_REMOVE_OID_STASH_ITERATE 00202 netsnmp_oid_stash_node * 00203 netsnmp_oid_stash_getnext_node(netsnmp_oid_stash_node *root, 00204 oid * lookup, size_t lookup_len) 00205 { 00206 netsnmp_oid_stash_node *curnode, *tmpp, *loopp; 00207 unsigned int i, j, bigger_than = 0, do_bigger = 0; 00208 00209 if (!root) 00210 return NULL; 00211 tmpp = NULL; 00212 00213 /* get closest matching node */ 00214 for (curnode = root, i = 0; i < lookup_len; i++) { 00215 tmpp = curnode->children[lookup[i] % curnode->children_size]; 00216 if (!tmpp) { 00217 break; 00218 } else { 00219 for (loopp = tmpp; loopp; loopp = loopp->next_sibling) { 00220 if (loopp->value == lookup[i]) 00221 break; 00222 } 00223 if (loopp) { 00224 tmpp = loopp; 00225 } else { 00226 break; 00227 } 00228 } 00229 curnode = tmpp; 00230 } 00231 00232 /* find the *next* node lexographically greater */ 00233 if (!curnode) 00234 return NULL; /* ack! */ 00235 00236 if (i+1 < lookup_len) { 00237 bigger_than = lookup[i+1]; 00238 do_bigger = 1; 00239 } 00240 00241 do { 00242 /* check the children first */ 00243 tmpp = NULL; 00244 /* next child must be (next) greater than our next search node */ 00245 /* XXX: should start this loop at best_nums[i]%... and wrap */ 00246 for(j = 0; j < curnode->children_size; j++) { 00247 for (loopp = curnode->children[j]; 00248 loopp; loopp = loopp->next_sibling) { 00249 if ((!do_bigger || loopp->value > bigger_than) && 00250 (!tmpp || tmpp->value > loopp->value)) { 00251 tmpp = loopp; 00252 /* XXX: can do better and include min_nums[i] */ 00253 if (tmpp->value <= curnode->children_size-1) { 00254 /* best we can do. */ 00255 goto done_this_loop; 00256 } 00257 } 00258 } 00259 } 00260 00261 done_this_loop: 00262 if (tmpp && tmpp->thedata) 00263 /* found a node with data. Go with it. */ 00264 return tmpp; 00265 00266 if (tmpp) { 00267 /* found a child node without data, maybe find a grandchild? */ 00268 do_bigger = 0; 00269 curnode = tmpp; 00270 } else { 00271 /* no respectable children (the bums), we'll have to go up. 00272 But to do so, they must be better than our current best_num + 1. 00273 */ 00274 do_bigger = 1; 00275 bigger_than = curnode->value; 00276 curnode = curnode->parent; 00277 } 00278 } while (curnode); 00279 00280 /* fell off the top */ 00281 return NULL; 00282 } 00283 #endif /* NETSNMP_FEATURE_REMOVE_OID_STASH_ITERATE */ 00284 00285 netsnmp_feature_child_of(oid_stash_get_data, oid_stash_all) 00286 #ifndef NETSNMP_FEATURE_REMOVE_OID_STASH_GET_DATA 00287 00296 void * 00297 netsnmp_oid_stash_get_data(netsnmp_oid_stash_node *root, 00298 const oid * lookup, size_t lookup_len) 00299 { 00300 netsnmp_oid_stash_node *ret; 00301 ret = netsnmp_oid_stash_get_node(root, lookup, lookup_len); 00302 if (ret) 00303 return ret->thedata; 00304 return NULL; 00305 } 00306 #endif /* NETSNMP_FEATURE_REMOVE_OID_STASH_GET_DATA */ 00307 00319 netsnmp_feature_child_of(oid_stash_store_all, oid_stash_all) 00320 #ifndef NETSNMP_FEATURE_REMOVE_OID_STASH_STORE_ALL 00321 int 00322 netsnmp_oid_stash_store_all(int majorID, int minorID, 00323 void *serverarg, void *clientarg) { 00324 oid oidbase[MAX_OID_LEN]; 00325 netsnmp_oid_stash_save_info *sinfo; 00326 00327 if (!clientarg) 00328 return SNMP_ERR_NOERROR; 00329 00330 sinfo = (netsnmp_oid_stash_save_info *) clientarg; 00331 netsnmp_oid_stash_store(*(sinfo->root), sinfo->token, sinfo->dumpfn, 00332 oidbase,0); 00333 return SNMP_ERR_NOERROR; 00334 } 00335 #endif /* NETSNMP_FEATURE_REMOVE_OID_STASH_STORE_ALL */ 00336 00352 void 00353 netsnmp_oid_stash_store(netsnmp_oid_stash_node *root, 00354 const char *tokenname, NetSNMPStashDump *dumpfn, 00355 oid *curoid, size_t curoid_len) { 00356 00357 char buf[SNMP_MAXBUF]; 00358 netsnmp_oid_stash_node *tmpp; 00359 char *cp; 00360 char *appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 00361 NETSNMP_DS_LIB_APPTYPE); 00362 int i; 00363 00364 if (!tokenname || !root || !curoid || !dumpfn) 00365 return; 00366 00367 for (i = 0; i < (int)root->children_size; i++) { 00368 if (root->children[i]) { 00369 for (tmpp = root->children[i]; tmpp; tmpp = tmpp->next_sibling) { 00370 curoid[curoid_len] = tmpp->value; 00371 if (tmpp->thedata) { 00372 snprintf(buf, sizeof(buf), "%s ", tokenname); 00373 cp = read_config_save_objid(buf+strlen(buf), curoid, 00374 curoid_len+1); 00375 *cp++ = ' '; 00376 *cp = '\0'; 00377 if ((*dumpfn)(cp, sizeof(buf) - strlen(buf), 00378 tmpp->thedata, tmpp)) 00379 read_config_store(appname, buf); 00380 } 00381 netsnmp_oid_stash_store(tmpp, tokenname, dumpfn, 00382 curoid, curoid_len+1); 00383 } 00384 } 00385 } 00386 } 00387 00392 void 00393 oid_stash_dump(netsnmp_oid_stash_node *root, char *prefix) 00394 { 00395 char myprefix[MAX_OID_LEN * 4]; 00396 netsnmp_oid_stash_node *tmpp; 00397 int prefix_len = strlen(prefix) + 1; /* actually it's +2 */ 00398 unsigned int i; 00399 00400 memset(myprefix, ' ', MAX_OID_LEN * 4); 00401 myprefix[prefix_len] = '\0'; 00402 00403 for (i = 0; i < root->children_size; i++) { 00404 if (root->children[i]) { 00405 for (tmpp = root->children[i]; tmpp; tmpp = tmpp->next_sibling) { 00406 printf("%s%" NETSNMP_PRIo "d@%d: %s\n", prefix, tmpp->value, i, 00407 (tmpp->thedata) ? "DATA" : ""); 00408 oid_stash_dump(tmpp, myprefix); 00409 } 00410 } 00411 } 00412 } 00413 00419 void 00420 netsnmp_oid_stash_free(netsnmp_oid_stash_node **root, 00421 NetSNMPStashFreeNode *freefn) { 00422 00423 netsnmp_oid_stash_node *curnode, *tmpp; 00424 unsigned int i; 00425 00426 if (!root || !*root) 00427 return; 00428 00429 /* loop through all our children and free each node */ 00430 for (i = 0; i < (*root)->children_size; i++) { 00431 if ((*root)->children[i]) { 00432 for(tmpp = (*root)->children[i]; tmpp; tmpp = curnode) { 00433 if (tmpp->thedata) { 00434 if (freefn) 00435 (*freefn)(tmpp->thedata); 00436 else 00437 free(tmpp->thedata); 00438 } 00439 curnode = tmpp->next_sibling; 00440 netsnmp_oid_stash_free(&tmpp, freefn); 00441 } 00442 } 00443 } 00444 free((*root)->children); 00445 free (*root); 00446 *root = NULL; 00447 } 00448 00449 #else /* NETSNMP_FEATURE_REMOVE_OID_STASH */ 00450 netsnmp_feature_unused(oid_stash); 00451 #endif/* NETSNMP_FEATURE_REMOVE_OID_STASH */ 00452 00453 #ifndef NETSNMP_FEATURE_REMOVE_OID_STASH_NO_FREE 00454 void 00455 netsnmp_oid_stash_no_free(void *bogus) 00456 { 00457 /* noop */ 00458 } 00459 #endif /* NETSNMP_FEATURE_REMOVE_OID_STASH_NO_FREE */ 00460