00001
00002
00003
00004
00005
00006 #include <net-snmp/net-snmp-config.h>
00007
00008 #if HAVE_STRING_H
00009 #include <string.h>
00010 #else
00011 #include <strings.h>
00012 #endif
00013
00014 #include <net-snmp/net-snmp-includes.h>
00015 #include <net-snmp/agent/net-snmp-agent-includes.h>
00016
00017 #include <net-snmp/agent/table.h>
00018 #include <net-snmp/agent/table_container.h>
00019 #include <net-snmp/library/container.h>
00020 #include <net-snmp/library/snmp_assert.h>
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 typedef struct container_table_data_s {
00036
00038 netsnmp_table_registration_info *tblreg_info;
00039
00041 netsnmp_container *table;
00042
00043
00044
00045
00046
00047
00048 char key_type;
00049
00050 } container_table_data;
00051
00135 static int
00136 _container_table_handler(netsnmp_mib_handler *handler,
00137 netsnmp_handler_registration *reginfo,
00138 netsnmp_agent_request_info *agtreq_info,
00139 netsnmp_request_info *requests);
00140
00141 static void *
00142 _find_next_row(netsnmp_container *c,
00143 netsnmp_table_request_info *tblreq,
00144 void * key);
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 container_table_data *
00163 netsnmp_tcontainer_create_table( const char *name,
00164 netsnmp_container *container, long flags )
00165 {
00166 container_table_data *table;
00167
00168 table = SNMP_MALLOC_TYPEDEF(container_table_data);
00169 if (!table)
00170 return NULL;
00171 if (container)
00172 table->table = container;
00173 else {
00174 table->table = netsnmp_container_find("table_container");
00175 if (!table->table) {
00176 SNMP_FREE(table);
00177 return NULL;
00178 }
00179 }
00180
00181 if (flags)
00182 table->key_type = flags & 0x03;
00183 else
00184 table->key_type = TABLE_CONTAINER_KEY_NETSNMP_INDEX;
00185
00186 if (!table->table->compare)
00187 table->table->compare = netsnmp_compare_netsnmp_index;
00188 if (!table->table->ncompare)
00189 table->table->ncompare = netsnmp_ncompare_netsnmp_index;
00190
00191 return table;
00192 }
00193
00194 void
00195 netsnmp_tcontainer_delete_table( container_table_data *table )
00196 {
00197 if (!table)
00198 return;
00199
00200 if (table->table)
00201 CONTAINER_FREE(table->table);
00202
00203 SNMP_FREE(table);
00204 return;
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214 int
00215 netsnmp_tcontainer_add_row( container_table_data *table, netsnmp_index *row )
00216 {
00217 if (!table || !table->table || !row)
00218 return -1;
00219 CONTAINER_INSERT( table->table, row );
00220 return 0;
00221 }
00222
00223 netsnmp_index *
00224 netsnmp_tcontainer_remove_row( container_table_data *table, netsnmp_index *row )
00225 {
00226 if (!table || !table->table || !row)
00227 return NULL;
00228 CONTAINER_REMOVE( table->table, row );
00229 return NULL;
00230 }
00231
00232 int
00233 netsnmp_tcontainer_replace_row( container_table_data *table,
00234 netsnmp_index *old_row, netsnmp_index *new_row )
00235 {
00236 if (!table || !table->table || !old_row || !new_row)
00237 return -1;
00238 netsnmp_tcontainer_remove_row( table, old_row );
00239 netsnmp_tcontainer_add_row( table, new_row );
00240 return 0;
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00253 netsnmp_mib_handler *
00254 netsnmp_container_table_handler_get(netsnmp_table_registration_info *tabreg,
00255 netsnmp_container *container, char key_type)
00256 {
00257 container_table_data *tad;
00258 netsnmp_mib_handler *handler;
00259
00260 if (NULL == tabreg) {
00261 snmp_log(LOG_ERR, "bad param in netsnmp_container_table_register\n");
00262 return NULL;
00263 }
00264
00265 tad = SNMP_MALLOC_TYPEDEF(container_table_data);
00266 handler = netsnmp_create_handler("table_container",
00267 _container_table_handler);
00268 if((NULL == tad) || (NULL == handler)) {
00269 if(tad) free(tad);
00270 if(handler) free(handler);
00271 snmp_log(LOG_ERR,
00272 "malloc failure in netsnmp_container_table_register\n");
00273 return NULL;
00274 }
00275
00276 tad->tblreg_info = tabreg;
00277 if(key_type)
00278 tad->key_type = key_type;
00279 else
00280 tad->key_type = TABLE_CONTAINER_KEY_NETSNMP_INDEX;
00281
00282 if(NULL == container)
00283 container = netsnmp_container_find("table_container");
00284 tad->table = container;
00285
00286 if (NULL==container->compare)
00287 container->compare = netsnmp_compare_netsnmp_index;
00288 if (NULL==container->ncompare)
00289 container->ncompare = netsnmp_ncompare_netsnmp_index;
00290
00291 handler->myvoid = (void*)tad;
00292 handler->flags |= MIB_HANDLER_AUTO_NEXT;
00293
00294 return handler;
00295 }
00296
00297 int
00298 netsnmp_container_table_register(netsnmp_handler_registration *reginfo,
00299 netsnmp_table_registration_info *tabreg,
00300 netsnmp_container *container, char key_type )
00301 {
00302 netsnmp_mib_handler *handler;
00303
00304 if ((NULL == reginfo) || (NULL == reginfo->handler) || (NULL == tabreg)) {
00305 snmp_log(LOG_ERR, "bad param in netsnmp_container_table_register\n");
00306 return SNMPERR_GENERR;
00307 }
00308
00309 if (NULL==container)
00310 container = netsnmp_container_find(reginfo->handlerName);
00311
00312 handler = netsnmp_container_table_handler_get(tabreg, container, key_type);
00313 netsnmp_inject_handler(reginfo, handler );
00314
00315 return netsnmp_register_table(reginfo, tabreg);
00316 }
00317
00319 netsnmp_container*
00320 netsnmp_container_table_container_extract(netsnmp_request_info *request)
00321 {
00322 return (netsnmp_container *)
00323 netsnmp_request_get_list_data(request, TABLE_CONTAINER_CONTAINER);
00324 }
00325
00326 #ifndef NETSNMP_USE_INLINE
00327
00328 void *
00329 netsnmp_container_table_row_extract(netsnmp_request_info *request)
00330 {
00331
00332
00333
00334
00335 return netsnmp_request_get_list_data(request, TABLE_CONTAINER_ROW);
00336 }
00338 void *
00339 netsnmp_container_table_extract_context(netsnmp_request_info *request)
00340 {
00341
00342
00343
00344
00345 return netsnmp_request_get_list_data(request, TABLE_CONTAINER_ROW);
00346 }
00347 #endif
00348
00350 void
00351 netsnmp_container_table_row_insert(netsnmp_request_info *request,
00352 netsnmp_index *row)
00353 {
00354 netsnmp_request_info *req;
00355 netsnmp_table_request_info *table_info = NULL;
00356 netsnmp_variable_list *this_index = NULL;
00357 netsnmp_variable_list *that_index = NULL;
00358 oid base_oid[] = {0, 0};
00359 oid this_oid[MAX_OID_LEN];
00360 oid that_oid[MAX_OID_LEN];
00361 size_t this_oid_len, that_oid_len;
00362
00363 if (!request)
00364 return;
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 table_info = netsnmp_extract_table_info(request);
00375 this_index = table_info->indexes;
00376 build_oid_noalloc(this_oid, MAX_OID_LEN, &this_oid_len,
00377 base_oid, 2, this_index);
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 for (req=request; req->prev; req=req->prev)
00390 ;
00391
00392
00393
00394
00395
00396 for (; req; req=req->next) {
00397 if (req->processed)
00398 continue;
00399
00400 table_info = netsnmp_extract_table_info(req);
00401 that_index = table_info->indexes;
00402 build_oid_noalloc(that_oid, MAX_OID_LEN, &that_oid_len,
00403 base_oid, 2, that_index);
00404
00405
00406
00407
00408
00409 if (snmp_oid_compare(this_oid, this_oid_len,
00410 that_oid, that_oid_len) == 0) {
00411 netsnmp_request_add_list_data(req,
00412 netsnmp_create_data_list(TABLE_CONTAINER_ROW, row, NULL));
00413 }
00414 }
00415 }
00416
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 NETSNMP_STATIC_INLINE void
00428 _set_key( container_table_data * tad, netsnmp_request_info *request,
00429 netsnmp_table_request_info *tblreq_info,
00430 void **key, netsnmp_index *index )
00431 {
00432 if (TABLE_CONTAINER_KEY_NETSNMP_INDEX == tad->key_type) {
00433 index->oids = tblreq_info->index_oid;
00434 index->len = tblreq_info->index_oid_len;
00435 *key = index;
00436 }
00437 else if (TABLE_CONTAINER_KEY_VARBIND_INDEX == tad->key_type) {
00438 *key = tblreq_info->indexes;
00439 }
00440 #if 0
00441 else if (TABLE_CONTAINER_KEY_VARBIND_RAW == tad->key_type) {
00442 *key = request->requestvb;
00443 }
00444 #endif
00445 else
00446 *key = NULL;
00447 }
00448
00449
00450 NETSNMP_STATIC_INLINE void
00451 _data_lookup(netsnmp_handler_registration *reginfo,
00452 netsnmp_agent_request_info *agtreq_info,
00453 netsnmp_request_info *request, container_table_data * tad)
00454 {
00455 netsnmp_index *row = NULL;
00456 netsnmp_table_request_info *tblreq_info;
00457 netsnmp_variable_list *var;
00458 netsnmp_index index;
00459 void *key;
00460
00461 var = request->requestvb;
00462
00463 DEBUGIF("table_container") {
00464 DEBUGMSGTL(("table_container", " data_lookup oid:"));
00465 DEBUGMSGOID(("table_container", var->name, var->name_length));
00466 DEBUGMSG(("table_container", "\n"));
00467 }
00468
00469
00470
00471
00472
00473 tblreq_info = netsnmp_extract_table_info(request);
00475 netsnmp_assert((NULL != tblreq_info) &&
00476 (tblreq_info->colnum <= tad->tblreg_info->max_column));
00477
00478 if ((agtreq_info->mode == MODE_GETNEXT) ||
00479 (agtreq_info->mode == MODE_GETBULK)) {
00480
00481
00482
00483
00484 _set_key( tad, request, tblreq_info, &key, &index );
00485 row = _find_next_row(tad->table, tblreq_info, key);
00486 if (row) {
00487
00488
00489
00490
00491 if(TABLE_CONTAINER_KEY_NETSNMP_INDEX == tad->key_type) {
00492 tblreq_info->index_oid_len = row->len;
00493 memcpy(tblreq_info->index_oid, row->oids,
00494 row->len * sizeof(oid));
00495 netsnmp_update_variable_list_from_index(tblreq_info);
00496 }
00497 else if (TABLE_CONTAINER_KEY_VARBIND_INDEX == tad->key_type) {
00500 netsnmp_update_indexes_from_variable_list(tblreq_info);
00501 }
00502
00503 if (TABLE_CONTAINER_KEY_VARBIND_RAW != tad->key_type) {
00504 netsnmp_table_build_oid_from_index(reginfo, request,
00505 tblreq_info);
00506 }
00507 }
00508 else {
00509
00510
00511
00512
00513
00514 netsnmp_set_request_error(agtreq_info, request, SNMP_ENDOFMIBVIEW);
00515 DEBUGMSGTL(("table_container", "no row found\n"));
00516 }
00517 }
00518 else {
00519
00520 _set_key( tad, request, tblreq_info, &key, &index );
00521 row = CONTAINER_FIND(tad->table, key);
00522 if (NULL == row) {
00523
00524
00525
00526 DEBUGMSGTL(("table_container", "no row found\n"));
00527 if((agtreq_info->mode != MODE_SET_RESERVE1) ||
00528 (reginfo->modes & HANDLER_CAN_NOT_CREATE)) {
00529 netsnmp_set_request_error(agtreq_info, request,
00530 SNMP_NOSUCHINSTANCE);
00531 }
00532 }
00533 }
00535
00536
00537
00538 if (SNMP_ENDOFMIBVIEW != request->requestvb->type) {
00539 if (NULL != row)
00540 netsnmp_request_add_list_data(request,
00541 netsnmp_create_data_list
00542 (TABLE_CONTAINER_ROW,
00543 row, NULL));
00544 netsnmp_request_add_list_data(request,
00545 netsnmp_create_data_list
00546 (TABLE_CONTAINER_CONTAINER,
00547 tad->table, NULL));
00548 }
00549 }
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 static int
00561 _container_table_handler(netsnmp_mib_handler *handler,
00562 netsnmp_handler_registration *reginfo,
00563 netsnmp_agent_request_info *agtreq_info,
00564 netsnmp_request_info *requests)
00565 {
00566 int rc = SNMP_ERR_NOERROR;
00567 int oldmode, need_processing = 0;
00568 container_table_data *tad;
00569
00571 netsnmp_assert((NULL != handler) && (NULL != handler->myvoid));
00572 netsnmp_assert((NULL != reginfo) && (NULL != agtreq_info));
00573
00574 DEBUGMSGTL(("table_container", "Mode %s, Got request:\n",
00575 se_find_label_in_slist("agent_mode",agtreq_info->mode)));
00576
00577
00578
00579
00580
00581
00582
00583 tad = (container_table_data *)handler->myvoid;
00584
00585
00586
00587
00588
00589
00590
00591
00592 oldmode = agtreq_info->mode;
00593 if(MODE_IS_GET(oldmode) || (MODE_SET_RESERVE1 == oldmode)) {
00594 netsnmp_request_info *curr_request;
00595
00596
00597
00598
00599 for (curr_request = requests; curr_request; curr_request = curr_request->next) {
00600
00601
00602
00603 if (curr_request->processed != 0) {
00604 DEBUGMSGTL(("table_container", "already processed\n"));
00605 continue;
00606 }
00607
00608
00609
00610
00611 _data_lookup(reginfo, agtreq_info, curr_request, tad);
00612
00613 if(curr_request->processed)
00614 continue;
00615
00616 ++need_processing;
00617 }
00618 }
00619
00620
00621
00622
00623
00624 if ((oldmode == MODE_GETNEXT) && (handler->next)) {
00625
00626
00627
00628 handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
00629
00630
00631
00632
00633
00634 if(need_processing > 0) {
00635 agtreq_info->mode = MODE_GET;
00636 rc = netsnmp_call_next_handler(handler, reginfo, agtreq_info,
00637 requests);
00638 if (rc != SNMP_ERR_NOERROR) {
00639 DEBUGMSGTL(("table_container",
00640 "next handler returned %d\n", rc));
00641 }
00642
00643 agtreq_info->mode = oldmode;
00644 }
00645 }
00646
00647 return rc;
00648 }
00652
00653
00654
00655
00656
00657
00658 static void *
00659 _find_next_row(netsnmp_container *c,
00660 netsnmp_table_request_info *tblreq,
00661 void * key)
00662 {
00663 void *row = NULL;
00664
00665 if (!c || !tblreq || !tblreq->reg_info ) {
00666 snmp_log(LOG_ERR,"_find_next_row param error\n");
00667 return NULL;
00668 }
00669
00670
00671
00672
00673 netsnmp_assert(tblreq->colnum >= tblreq->reg_info->min_column);
00674
00675
00676
00677
00678 if(tblreq->number_indexes == 0) {
00679 row = CONTAINER_FIRST(c);
00680 } else {
00681
00682 if(NULL == key) {
00683 netsnmp_index index;
00684 index.oids = tblreq->index_oid;
00685 index.len = tblreq->index_oid_len;
00686 row = CONTAINER_NEXT(c, &index);
00687 }
00688 else
00689 row = CONTAINER_NEXT(c, key);
00690
00691
00692
00693
00694
00695 if (NULL == row) {
00696
00697
00698
00699
00700 oid next_col = netsnmp_table_next_column(tblreq);
00701 if (0 != next_col) {
00702 tblreq->colnum = next_col;
00703 row = CONTAINER_FIRST(c);
00704 }
00705 }
00706 }
00707
00708 return row;
00709 }
00710
00720 netsnmp_index *
00721 netsnmp_table_index_find_next_row(netsnmp_container *c,
00722 netsnmp_table_request_info *tblreq)
00723 {
00724 return _find_next_row(c, tblreq, NULL );
00725 }
00726
00727
00728
00729
00730
00731
00732