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