00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <net-snmp/net-snmp-config.h>
00012 #include <net-snmp/net-snmp-includes.h>
00013 #include <net-snmp/library/container.h>
00014 #include <net-snmp/library/container_binary_array.h>
00015 #include <net-snmp/library/container_list_ssll.h>
00016 #include <net-snmp/library/container_null.h>
00017
00021
00022
00023 static netsnmp_container *containers = NULL;
00024
00025 typedef struct container_type_s {
00026 const char *name;
00027 netsnmp_factory *factory;
00028 netsnmp_container_compare *compare;
00029 } container_type;
00030
00031 netsnmp_factory *
00032 netsnmp_container_get_factory(const char *type);
00033
00034
00035
00036 static void
00037 _factory_free(void *dat, void *context)
00038 {
00039 container_type *data = (container_type *)dat;
00040 if (data == NULL)
00041 return;
00042
00043 if (data->name != NULL) {
00044 DEBUGMSGTL(("container", " _factory_free_list() called for %s\n",
00045 data->name));
00046 free((void *)data->name);
00047 }
00048 free(data);
00049 }
00050
00051
00052
00053 void
00054 netsnmp_container_init_list(void)
00055 {
00056 if (NULL != containers)
00057 return;
00058
00059
00060
00061
00062
00063 containers = netsnmp_container_get_binary_array();
00064 containers->compare = netsnmp_compare_cstring;
00065
00066
00067
00068
00069 netsnmp_container_binary_array_init();
00070 netsnmp_container_ssll_init();
00071 netsnmp_container_null_init();
00072
00073
00074
00075
00076 netsnmp_container_register("table_container",
00077 netsnmp_container_get_factory("binary_array"));
00078 netsnmp_container_register("linked_list",
00079 netsnmp_container_get_factory("sorted_singly_linked_list"));
00080 netsnmp_container_register("ssll_container",
00081 netsnmp_container_get_factory("sorted_singly_linked_list"));
00082
00083 netsnmp_container_register_with_compare
00084 ("cstring", netsnmp_container_get_factory("binary_array"),
00085 netsnmp_compare_direct_cstring);
00086
00087 netsnmp_container_register_with_compare
00088 ("string", netsnmp_container_get_factory("binary_array"),
00089 netsnmp_compare_cstring);
00090 netsnmp_container_register_with_compare
00091 ("string_binary_array", netsnmp_container_get_factory("binary_array"),
00092 netsnmp_compare_cstring);
00093
00094 }
00095
00096 void
00097 netsnmp_container_free_list(void)
00098 {
00099 DEBUGMSGTL(("container", "netsnmp_container_free_list() called\n"));
00100 if (containers == NULL)
00101 return;
00102
00103
00104
00105
00106 CONTAINER_FOR_EACH(containers, ((netsnmp_container_obj_func *)_factory_free), NULL);
00107
00108
00109
00110
00111 CONTAINER_FREE(containers);
00112 containers = NULL;
00113 }
00114
00115 int
00116 netsnmp_container_register_with_compare(const char* name, netsnmp_factory *f,
00117 netsnmp_container_compare *c)
00118 {
00119 container_type *ct, tmp;
00120
00121 if (NULL==containers)
00122 return -1;
00123
00124 tmp.name = (char *)name;
00125 ct = (container_type *)CONTAINER_FIND(containers, &tmp);
00126 if (NULL!=ct) {
00127 DEBUGMSGT(("container_registry",
00128 "replacing previous container factory\n"));
00129 ct->factory = f;
00130 }
00131 else {
00132 ct = SNMP_MALLOC_TYPEDEF(container_type);
00133 if (NULL == ct)
00134 return -1;
00135 ct->name = strdup(name);
00136 ct->factory = f;
00137 ct->compare = c;
00138 CONTAINER_INSERT(containers, ct);
00139 }
00140 DEBUGMSGT(("container_registry", "registered container factory %s (%s)\n",
00141 ct->name, f->product));
00142
00143 return 0;
00144 }
00145
00146 int
00147 netsnmp_container_register(const char* name, netsnmp_factory *f)
00148 {
00149 return netsnmp_container_register_with_compare(name, f, NULL);
00150 }
00151
00152
00153
00154 netsnmp_factory *
00155 netsnmp_container_get_factory(const char *type)
00156 {
00157 container_type ct, *found;
00158
00159 if (NULL==containers)
00160 return NULL;
00161
00162 ct.name = type;
00163 found = (container_type *)CONTAINER_FIND(containers, &ct);
00164
00165 return found ? found->factory : NULL;
00166 }
00167
00168 netsnmp_factory *
00169 netsnmp_container_find_factory(const char *type_list)
00170 {
00171 netsnmp_factory *f = NULL;
00172 char *list, *entry;
00173 char *st = NULL;
00174
00175 if (NULL==type_list)
00176 return NULL;
00177
00178 list = strdup(type_list);
00179 entry = strtok_r(list, ":", &st);
00180 while(entry) {
00181 f = netsnmp_container_get_factory(entry);
00182 if (NULL != f)
00183 break;
00184 entry = strtok_r(NULL, ":", &st);
00185 }
00186
00187 free(list);
00188 return f;
00189 }
00190
00191
00192
00193 static container_type *
00194 netsnmp_container_get_ct(const char *type)
00195 {
00196 container_type ct;
00197
00198 if (NULL == containers)
00199 return NULL;
00200
00201 ct.name = type;
00202 return (container_type *)CONTAINER_FIND(containers, &ct);
00203 }
00204
00205 static container_type *
00206 netsnmp_container_find_ct(const char *type_list)
00207 {
00208 container_type *ct = NULL;
00209 char *list, *entry;
00210 char *st = NULL;
00211
00212 if (NULL==type_list)
00213 return NULL;
00214
00215 list = strdup(type_list);
00216 entry = strtok_r(list, ":", &st);
00217 while(entry) {
00218 ct = netsnmp_container_get_ct(entry);
00219 if (NULL != ct)
00220 break;
00221 entry = strtok_r(NULL, ":", &st);
00222 }
00223
00224 free(list);
00225 return ct;
00226 }
00227
00228
00229
00230
00231
00232 netsnmp_container *
00233 netsnmp_container_get(const char *type)
00234 {
00235 netsnmp_container *c;
00236 container_type *ct = netsnmp_container_get_ct(type);
00237 if (ct) {
00238 c = (netsnmp_container *)(ct->factory->produce());
00239 if (c && ct->compare)
00240 c->compare = ct->compare;
00241 return c;
00242 }
00243
00244 return NULL;
00245 }
00246
00247
00248
00249 netsnmp_container *
00250 netsnmp_container_find(const char *type)
00251 {
00252 container_type *ct = netsnmp_container_find_ct(type);
00253 netsnmp_container *c = ct ? (netsnmp_container *)(ct->factory->produce()) : NULL;
00254
00255
00256
00257
00258 if (c) {
00259 if (ct->compare)
00260 c->compare = ct->compare;
00261 else if (NULL == c->compare)
00262 c->compare = netsnmp_compare_netsnmp_index;
00263 }
00264
00265 return c;
00266 }
00267
00268
00269
00270 void
00271 netsnmp_container_add_index(netsnmp_container *primary,
00272 netsnmp_container *new_index)
00273 {
00274 netsnmp_container *curr = primary;
00275
00276 if((NULL == new_index) || (NULL == primary)) {
00277 snmp_log(LOG_ERR, "add index called with null pointer\n");
00278 return;
00279 }
00280
00281 while(curr->next)
00282 curr = curr->next;
00283
00284 curr->next = new_index;
00285 new_index->prev = curr;
00286 }
00287
00288 #ifndef NETSNMP_USE_INLINE
00289
00290
00291
00292
00293
00294 int CONTAINER_INSERT_HELPER(netsnmp_container* x, const void* k)
00295 {
00296 while(x && x->insert_filter && x->insert_filter(x,k) == 1)
00297 x = x->next;
00298 if(x) {
00299 int rc = x->insert(x,k);
00300 if(rc)
00301 snmp_log(LOG_DEBUG,"error on subcontainer '%s' insert (%d)\n",
00302 x->container_name ? x->container_name : "", rc);
00303 else {
00304 rc = CONTAINER_INSERT_HELPER(x->next, k);
00305 if(rc)
00306 x->remove(x,k);
00307 }
00308 return rc;
00309 }
00310 return 0;
00311 }
00312
00313
00314
00315
00316
00317 int CONTAINER_INSERT(netsnmp_container* x, const void* k)
00318 {
00320 while(x->prev)
00321 x = x->prev;
00322 return CONTAINER_INSERT_HELPER(x, k);
00323 }
00324
00325
00326
00327
00328
00329 int CONTAINER_REMOVE(netsnmp_container *x, const void *k)
00330 {
00331 int rc2, rc = 0;
00332
00334 while(x->next)
00335 x = x->next;
00336 while(x) {
00337 rc2 = x->remove(x,k);
00339 if ((rc2) && (NULL == x->insert_filter)) {
00340 snmp_log(LOG_ERR,"error on subcontainer '%s' remove (%d)\n",
00341 x->container_name ? x->container_name : "", rc2);
00342 rc = rc2;
00343 }
00344 x = x->prev;
00345
00346 }
00347 return rc;
00348 }
00349
00350
00351
00352
00353
00354 int CONTAINER_FREE(netsnmp_container *x)
00355 {
00356 int rc2, rc = 0;
00357
00359 while(x->next)
00360 x = x->next;
00361 while(x) {
00362 netsnmp_container *tmp;
00363 const char *name;
00364 tmp = x->prev;
00365 name = x->container_name;
00366 if (NULL != x->container_name)
00367 SNMP_FREE(x->container_name);
00368 rc2 = x->cfree(x);
00369 if (rc2) {
00370 snmp_log(LOG_ERR,"error on subcontainer '%s' cfree (%d)\n",
00371 name ? name : "", rc2);
00372 rc = rc2;
00373 }
00374 x = tmp;
00375 }
00376 return rc;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f,
00389 void *c)
00390 {
00392 while(x->next)
00393 x = x->next;
00394 while(x->prev) {
00395 x->clear(x, NULL, c);
00396 x = x->prev;
00397 }
00398 x->clear(x, f, c);
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408 netsnmp_container *SUBCONTAINER_FIND(netsnmp_container *x,
00409 const char* name)
00410 {
00411 if ((NULL == x) || (NULL == name))
00412 return NULL;
00413
00415 while(x->prev)
00416 x = x->prev;
00417 while(x) {
00418 if ((NULL != x->container_name) && (0 == strcmp(name,x->container_name)))
00419 break;
00420 x = x->next;
00421 }
00422 return x;
00423 }
00424 #endif
00425
00426
00427
00428
00429 void
00430 netsnmp_init_container(netsnmp_container *c,
00431 netsnmp_container_rc *init,
00432 netsnmp_container_rc *cfree,
00433 netsnmp_container_size *size,
00434 netsnmp_container_compare *cmp,
00435 netsnmp_container_op *ins,
00436 netsnmp_container_op *rem,
00437 netsnmp_container_rtn *fnd)
00438 {
00439 if (c == NULL)
00440 return;
00441
00442 c->init = init;
00443 c->cfree = cfree;
00444 c->get_size = size;
00445 c->compare = cmp;
00446 c->insert = ins;
00447 c->remove = rem;
00448 c->find = fnd;
00449 }
00450
00451
00452
00453
00454
00455
00456 int
00457 netsnmp_compare_netsnmp_index(const void *lhs, const void *rhs)
00458 {
00459 int rc;
00460 netsnmp_assert((NULL != lhs) && (NULL != rhs));
00461 DEBUGIF("compare:index") {
00462 DEBUGMSGT(("compare:index", "compare "));
00463 DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) lhs)->oids,
00464 ((const netsnmp_index *) lhs)->len));
00465 DEBUGMSG(("compare:index", " to "));
00466 DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) rhs)->oids,
00467 ((const netsnmp_index *) rhs)->len));
00468 DEBUGMSG(("compare:index", "\n"));
00469 }
00470 rc = snmp_oid_compare(((const netsnmp_index *) lhs)->oids,
00471 ((const netsnmp_index *) lhs)->len,
00472 ((const netsnmp_index *) rhs)->oids,
00473 ((const netsnmp_index *) rhs)->len);
00474 DEBUGMSGT(("compare:index", "result was %d\n", rc));
00475 return rc;
00476 }
00477
00478 int
00479 netsnmp_ncompare_netsnmp_index(const void *lhs, const void *rhs)
00480 {
00481 int rc;
00482 netsnmp_assert((NULL != lhs) && (NULL != rhs));
00483 DEBUGIF("compare:index") {
00484 DEBUGMSGT(("compare:index", "compare "));
00485 DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) lhs)->oids,
00486 ((const netsnmp_index *) lhs)->len));
00487 DEBUGMSG(("compare:index", " to "));
00488 DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) rhs)->oids,
00489 ((const netsnmp_index *) rhs)->len));
00490 DEBUGMSG(("compare:index", "\n"));
00491 }
00492 rc = snmp_oid_ncompare(((const netsnmp_index *) lhs)->oids,
00493 ((const netsnmp_index *) lhs)->len,
00494 ((const netsnmp_index *) rhs)->oids,
00495 ((const netsnmp_index *) rhs)->len,
00496 ((const netsnmp_index *) rhs)->len);
00497 DEBUGMSGT(("compare:index", "result was %d\n", rc));
00498 return rc;
00499 }
00500
00501 int
00502 netsnmp_compare_cstring(const void * lhs, const void * rhs)
00503 {
00504 return strcmp(((const container_type*)lhs)->name,
00505 ((const container_type*)rhs)->name);
00506 }
00507
00508 int
00509 netsnmp_ncompare_cstring(const void * lhs, const void * rhs)
00510 {
00511 return strncmp(((const container_type*)lhs)->name,
00512 ((const container_type*)rhs)->name,
00513 strlen(((const container_type*)rhs)->name));
00514 }
00515
00516 int
00517 netsnmp_compare_direct_cstring(const void * lhs, const void * rhs)
00518 {
00519 return strcmp((const char*)lhs, (const char*)rhs);
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529 int
00530 netsnmp_compare_mem(const char * lhs, size_t lhs_len,
00531 const char * rhs, size_t rhs_len)
00532 {
00533 int rc, min = SNMP_MIN(lhs_len, rhs_len);
00534
00535 rc = memcmp(lhs, rhs, min);
00536 if((rc==0) && (lhs_len != rhs_len)) {
00537 if(lhs_len < rhs_len)
00538 rc = -1;
00539 else
00540 rc = 1;
00541 }
00542
00543 return rc;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552 void
00553 netsnmp_container_simple_free(void *data, void *context)
00554 {
00555 if (data == NULL)
00556 return;
00557
00558 DEBUGMSGTL(("verbose:container",
00559 "netsnmp_container_simple_free) called for %p/%p\n",
00560 data, context));
00561 free((void*)data);
00562 }