net-snmp
5.4.1
|
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-includes.h> 00009 00018 /* 00019 * xxx-rks: when you have some spare time: 00020 * 00021 * b) basically, everything currently creates one node per sub-oid, 00022 * which is less than optimal. add code to create nodes with the 00023 * longest possible OID per node, and split nodes when necessary 00024 * during adds. 00025 * 00026 * c) If you are feeling really ambitious, also merge split nodes if 00027 * possible on a delete. 00028 * 00029 * xxx-wes: uh, right, like I *ever* have that much time. 00030 * 00031 */ 00032 00033 /*************************************************************************** 00034 * 00035 * 00036 ***************************************************************************/ 00037 00045 netsnmp_oid_stash_node * 00046 netsnmp_oid_stash_create_sized_node(size_t mysize) 00047 { 00048 netsnmp_oid_stash_node *ret; 00049 ret = SNMP_MALLOC_TYPEDEF(netsnmp_oid_stash_node); 00050 if (!ret) 00051 return NULL; 00052 ret->children = (netsnmp_oid_stash_node**) calloc(mysize, sizeof(netsnmp_oid_stash_node *)); 00053 if (!ret->children) { 00054 free(ret); 00055 return NULL; 00056 } 00057 ret->children_size = mysize; 00058 return ret; 00059 } 00060 00065 NETSNMP_INLINE netsnmp_oid_stash_node * 00066 netsnmp_oid_stash_create_node(void) 00067 { 00068 return netsnmp_oid_stash_create_sized_node(OID_STASH_CHILDREN_SIZE); 00069 } 00070 00082 int 00083 netsnmp_oid_stash_add_data(netsnmp_oid_stash_node **root, 00084 oid * lookup, size_t lookup_len, void *mydata) 00085 { 00086 netsnmp_oid_stash_node *curnode, *tmpp, *loopp; 00087 unsigned int i; 00088 00089 if (!root || !lookup || lookup_len == 0) 00090 return SNMPERR_GENERR; 00091 00092 if (!*root) { 00093 *root = netsnmp_oid_stash_create_node(); 00094 if (!*root) 00095 return SNMPERR_MALLOC; 00096 } 00097 DEBUGMSGTL(( "oid_stash", "stash_add_data ")); 00098 DEBUGMSGOID(("oid_stash", lookup, lookup_len)); 00099 DEBUGMSG(( "oid_stash", "\n")); 00100 tmpp = NULL; 00101 for (curnode = *root, i = 0; i < lookup_len; i++) { 00102 tmpp = curnode->children[lookup[i] % curnode->children_size]; 00103 if (!tmpp) { 00104 /* 00105 * no child in array at all 00106 */ 00107 tmpp = curnode->children[lookup[i] % curnode->children_size] = 00108 netsnmp_oid_stash_create_node(); 00109 tmpp->value = lookup[i]; 00110 tmpp->parent = curnode; 00111 } else { 00112 for (loopp = tmpp; loopp; loopp = loopp->next_sibling) { 00113 if (loopp->value == lookup[i]) 00114 break; 00115 } 00116 if (loopp) { 00117 tmpp = loopp; 00118 } else { 00119 /* 00120 * none exists. Create it 00121 */ 00122 loopp = netsnmp_oid_stash_create_node(); 00123 loopp->value = lookup[i]; 00124 loopp->next_sibling = tmpp; 00125 loopp->parent = curnode; 00126 tmpp->prev_sibling = loopp; 00127 curnode->children[lookup[i] % curnode->children_size] = 00128 loopp; 00129 tmpp = loopp; 00130 } 00131 /* 00132 * tmpp now points to the proper node 00133 */ 00134 } 00135 curnode = tmpp; 00136 } 00137 /* 00138 * tmpp now points to the exact match 00139 */ 00140 if (curnode->thedata) 00141 return SNMPERR_GENERR; 00142 if (NULL == tmpp) 00143 return SNMPERR_GENERR; 00144 tmpp->thedata = mydata; 00145 return SNMPERR_SUCCESS; 00146 } 00147 00153 netsnmp_oid_stash_node * 00154 netsnmp_oid_stash_get_node(netsnmp_oid_stash_node *root, 00155 oid * lookup, size_t lookup_len) 00156 { 00157 netsnmp_oid_stash_node *curnode, *tmpp, *loopp; 00158 unsigned int i; 00159 00160 if (!root) 00161 return NULL; 00162 tmpp = NULL; 00163 for (curnode = root, i = 0; i < lookup_len; i++) { 00164 tmpp = curnode->children[lookup[i] % curnode->children_size]; 00165 if (!tmpp) { 00166 return NULL; 00167 } else { 00168 for (loopp = tmpp; loopp; loopp = loopp->next_sibling) { 00169 if (loopp->value == lookup[i]) 00170 break; 00171 } 00172 if (loopp) { 00173 tmpp = loopp; 00174 } else { 00175 return NULL; 00176 } 00177 } 00178 curnode = tmpp; 00179 } 00180 return tmpp; 00181 } 00182 00190 netsnmp_oid_stash_node * 00191 netsnmp_oid_stash_getnext_node(netsnmp_oid_stash_node *root, 00192 oid * lookup, size_t lookup_len) 00193 { 00194 netsnmp_oid_stash_node *curnode, *tmpp, *loopp; 00195 unsigned int i, j, bigger_than = 0, do_bigger = 0; 00196 00197 if (!root) 00198 return NULL; 00199 tmpp = NULL; 00200 00201 /* get closest matching node */ 00202 for (curnode = root, i = 0; i < lookup_len; i++) { 00203 tmpp = curnode->children[lookup[i] % curnode->children_size]; 00204 if (!tmpp) { 00205 break; 00206 } else { 00207 for (loopp = tmpp; loopp; loopp = loopp->next_sibling) { 00208 if (loopp->value == lookup[i]) 00209 break; 00210 } 00211 if (loopp) { 00212 tmpp = loopp; 00213 } else { 00214 break; 00215 } 00216 } 00217 curnode = tmpp; 00218 } 00219 00220 /* find the *next* node lexographically greater */ 00221 if (!curnode) 00222 return NULL; /* ack! */ 00223 00224 if (i+1 < lookup_len) { 00225 bigger_than = lookup[i+1]; 00226 do_bigger = 1; 00227 } 00228 00229 do { 00230 /* check the children first */ 00231 tmpp = NULL; 00232 /* next child must be (next) greater than our next search node */ 00233 /* XXX: should start this loop at best_nums[i]%... and wrap */ 00234 for(j = 0; j < curnode->children_size; j++) { 00235 for (loopp = curnode->children[j]; 00236 loopp; loopp = loopp->next_sibling) { 00237 if ((!do_bigger || loopp->value > bigger_than) && 00238 (!tmpp || tmpp->value > loopp->value)) { 00239 tmpp = loopp; 00240 /* XXX: can do better and include min_nums[i] */ 00241 if (tmpp->value <= curnode->children_size-1) { 00242 /* best we can do. */ 00243 goto done_this_loop; 00244 } 00245 } 00246 } 00247 } 00248 00249 done_this_loop: 00250 if (tmpp && tmpp->thedata) 00251 /* found a node with data. Go with it. */ 00252 return tmpp; 00253 00254 if (tmpp) { 00255 /* found a child node without data, maybe find a grandchild? */ 00256 do_bigger = 0; 00257 curnode = tmpp; 00258 } else { 00259 /* no respectable children (the bums), we'll have to go up. 00260 But to do so, they must be better than our current best_num + 1. 00261 */ 00262 do_bigger = 1; 00263 bigger_than = curnode->value; 00264 curnode = curnode->parent; 00265 } 00266 } while (curnode); 00267 00268 /* fell off the top */ 00269 return NULL; 00270 } 00271 00281 void * 00282 netsnmp_oid_stash_get_data(netsnmp_oid_stash_node *root, 00283 oid * lookup, size_t lookup_len) 00284 { 00285 netsnmp_oid_stash_node *ret; 00286 ret = netsnmp_oid_stash_get_node(root, lookup, lookup_len); 00287 if (ret) 00288 return ret->thedata; 00289 return NULL; 00290 } 00291 00303 int 00304 netsnmp_oid_stash_store_all(int majorID, int minorID, 00305 void *serverarg, void *clientarg) { 00306 oid oidbase[MAX_OID_LEN]; 00307 netsnmp_oid_stash_save_info *sinfo; 00308 00309 if (!clientarg) 00310 return SNMP_ERR_NOERROR; 00311 00312 sinfo = (netsnmp_oid_stash_save_info *) clientarg; 00313 netsnmp_oid_stash_store(*(sinfo->root), sinfo->token, sinfo->dumpfn, 00314 oidbase,0); 00315 return SNMP_ERR_NOERROR; 00316 } 00317 00333 void 00334 netsnmp_oid_stash_store(netsnmp_oid_stash_node *root, 00335 const char *tokenname, NetSNMPStashDump *dumpfn, 00336 oid *curoid, size_t curoid_len) { 00337 00338 char buf[SNMP_MAXBUF]; 00339 netsnmp_oid_stash_node *tmpp; 00340 char *cp; 00341 char *appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 00342 NETSNMP_DS_LIB_APPTYPE); 00343 int i; 00344 00345 if (!tokenname || !root || !curoid || !dumpfn) 00346 return; 00347 00348 for (i = 0; i < (int)root->children_size; i++) { 00349 if (root->children[i]) { 00350 for (tmpp = root->children[i]; tmpp; tmpp = tmpp->next_sibling) { 00351 curoid[curoid_len] = tmpp->value; 00352 if (tmpp->thedata) { 00353 snprintf(buf, sizeof(buf), "%s ", tokenname); 00354 cp = read_config_save_objid(buf+strlen(buf), curoid, 00355 curoid_len+1); 00356 *cp++ = ' '; 00357 *cp = '\0'; 00358 if ((*dumpfn)(cp, sizeof(buf) - strlen(buf), 00359 tmpp->thedata, tmpp)) 00360 read_config_store(appname, buf); 00361 } 00362 netsnmp_oid_stash_store(tmpp, tokenname, dumpfn, 00363 curoid, curoid_len+1); 00364 } 00365 } 00366 } 00367 } 00368 00373 void 00374 oid_stash_dump(netsnmp_oid_stash_node *root, char *prefix) 00375 { 00376 char myprefix[MAX_OID_LEN * 4]; 00377 netsnmp_oid_stash_node *tmpp; 00378 int prefix_len = strlen(prefix) + 1; /* actually it's +2 */ 00379 unsigned int i; 00380 00381 memset(myprefix, ' ', MAX_OID_LEN * 4); 00382 myprefix[prefix_len] = '\0'; 00383 00384 for (i = 0; i < root->children_size; i++) { 00385 if (root->children[i]) { 00386 for (tmpp = root->children[i]; tmpp; tmpp = tmpp->next_sibling) { 00387 printf("%s%ld@%d: %s\n", prefix, tmpp->value, i, 00388 (tmpp->thedata) ? "DATA" : ""); 00389 oid_stash_dump(tmpp, myprefix); 00390 } 00391 } 00392 } 00393 } 00394 00400 void 00401 netsnmp_oid_stash_free(netsnmp_oid_stash_node **root, 00402 NetSNMPStashFreeNode *freefn) { 00403 00404 netsnmp_oid_stash_node *curnode, *tmpp; 00405 unsigned int i; 00406 00407 if (!root || !*root) 00408 return; 00409 00410 /* loop through all our children and free each node */ 00411 for (i = 0; i < (*root)->children_size; i++) { 00412 if ((*root)->children[i]) { 00413 for(tmpp = (*root)->children[i]; tmpp; tmpp = curnode) { 00414 if (tmpp->thedata) { 00415 if (freefn) 00416 (*freefn)(tmpp->thedata); 00417 else 00418 free(tmpp->thedata); 00419 } 00420 curnode = tmpp->next_sibling; 00421 netsnmp_oid_stash_free(&tmpp, freefn); 00422 } 00423 } 00424 } 00425 free((*root)->children); 00426 free (*root); 00427 *root = NULL; 00428 } 00429 00430 void 00431 netsnmp_oid_stash_no_free(void *bogus) 00432 { 00433 /* noop */ 00434 } 00435