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
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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 = 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
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
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
00133
00134 }
00135 curnode = tmpp;
00136 }
00137
00138
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
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
00221 if (!curnode)
00222 return NULL;
00223
00224 if (i+1 < lookup_len) {
00225 bigger_than = lookup[i+1];
00226 do_bigger = 1;
00227 }
00228
00229 do {
00230
00231 tmpp = NULL;
00232
00233
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
00241 if (tmpp->value <= curnode->children_size-1) {
00242
00243 goto done_this_loop;
00244 }
00245 }
00246 }
00247 }
00248
00249 done_this_loop:
00250 if (tmpp && tmpp->thedata)
00251
00252 return tmpp;
00253
00254 if (tmpp) {
00255
00256 do_bigger = 0;
00257 curnode = tmpp;
00258 } else {
00259
00260
00261
00262 do_bigger = 1;
00263 bigger_than = curnode->value;
00264 curnode = curnode->parent;
00265 }
00266 } while (curnode);
00267
00268
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 = 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;
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
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
00434 }
00435