00001 #include <net-snmp/net-snmp-config.h>
00002
00003 #if HAVE_STRING_H
00004 #include <string.h>
00005 #else
00006 #include <strings.h>
00007 #endif
00008
00009 #include <net-snmp/net-snmp-includes.h>
00010 #include <net-snmp/agent/net-snmp-agent-includes.h>
00011
00012 static netsnmp_data_list *auto_tables;
00013
00014 typedef struct data_set_tables_s {
00015 netsnmp_table_data_set *table_set;
00016 } data_set_tables;
00017
00018 typedef struct data_set_cache_s {
00019 void *data;
00020 size_t data_len;
00021 } data_set_cache;
00022
00023 #define STATE_ACTION 1
00024 #define STATE_COMMIT 2
00025 #define STATE_UNDO 3
00026 #define STATE_FREE 4
00027
00028 typedef struct newrow_stash_s {
00029 netsnmp_table_row *newrow;
00030 int state;
00031 int created;
00032 int deleted;
00033 } newrow_stash;
00034
00061 void
00062 netsnmp_init_table_dataset(void) {
00063 #ifndef DISABLE_MIB_LOADING
00064 register_app_config_handler("table",
00065 netsnmp_config_parse_table_set, NULL,
00066 "tableoid");
00067 #endif
00068 register_app_config_handler("add_row", netsnmp_config_parse_add_row,
00069 NULL, "table_name indexes... values...");
00070 }
00071
00072
00073
00074
00075
00076
00077
00079 netsnmp_table_data_set *
00080 netsnmp_create_table_data_set(const char *table_name)
00081 {
00082 netsnmp_table_data_set *table_set =
00083 SNMP_MALLOC_TYPEDEF(netsnmp_table_data_set);
00084 if (!table_set)
00085 return NULL;
00086 table_set->table = netsnmp_create_table_data(table_name);
00087 return table_set;
00088 }
00089
00091 netsnmp_table_row *
00092 netsnmp_table_data_set_clone_row(netsnmp_table_row *row)
00093 {
00094 netsnmp_table_data_set_storage *data, **newrowdata;
00095 netsnmp_table_row *newrow;
00096
00097 if (!row)
00098 return NULL;
00099
00100 newrow = netsnmp_table_data_clone_row(row);
00101 if (!newrow)
00102 return NULL;
00103
00104 data = (netsnmp_table_data_set_storage *) row->data;
00105
00106 if (data) {
00107 for (newrowdata =
00108 (netsnmp_table_data_set_storage **) &(newrow->data); data;
00109 newrowdata = &((*newrowdata)->next), data = data->next) {
00110
00111 memdup((u_char **) newrowdata, (u_char *) data,
00112 sizeof(netsnmp_table_data_set_storage));
00113 if (!*newrowdata) {
00114 netsnmp_table_dataset_delete_row(newrow);
00115 return NULL;
00116 }
00117
00118 if (data->data.voidp) {
00119 memdup((u_char **) & ((*newrowdata)->data.voidp),
00120 (u_char *) data->data.voidp, data->data_len);
00121 if (!(*newrowdata)->data.voidp) {
00122 netsnmp_table_dataset_delete_row(newrow);
00123 return NULL;
00124 }
00125 }
00126 }
00127 }
00128 return newrow;
00129 }
00130
00134 NETSNMP_INLINE netsnmp_table_data_set_storage *
00135 netsnmp_table_dataset_delete_data(netsnmp_table_data_set_storage *data)
00136 {
00137 netsnmp_table_data_set_storage *nextPtr = NULL;
00138 if (data) {
00139 nextPtr = data->next;
00140 SNMP_FREE(data->data.voidp);
00141 }
00142 SNMP_FREE(data);
00143 return nextPtr;
00144 }
00145
00147 NETSNMP_INLINE void
00148 netsnmp_table_dataset_delete_all_data(netsnmp_table_data_set_storage *data)
00149 {
00150
00151 while (data) {
00152 data = netsnmp_table_dataset_delete_data(data);
00153 }
00154 }
00155
00157 NETSNMP_INLINE void
00158 netsnmp_table_dataset_delete_row(netsnmp_table_row *row)
00159 {
00160 netsnmp_table_data_set_storage *data;
00161
00162 if (!row)
00163 return;
00164
00165 data = netsnmp_table_data_delete_row(row);
00166 netsnmp_table_dataset_delete_all_data(data);
00167 }
00168
00170 NETSNMP_INLINE void
00171 netsnmp_table_dataset_add_row(netsnmp_table_data_set *table,
00172 netsnmp_table_row *row)
00173 {
00174 if (!table)
00175 return;
00176 netsnmp_table_data_add_row(table->table, row);
00177 }
00178
00180 NETSNMP_INLINE void
00181 netsnmp_table_dataset_replace_row(netsnmp_table_data_set *table,
00182 netsnmp_table_row *origrow,
00183 netsnmp_table_row *newrow)
00184 {
00185 if (!table)
00186 return;
00187 netsnmp_table_data_replace_row(table->table, origrow, newrow);
00188 }
00189
00191 NETSNMP_INLINE void
00192 netsnmp_table_dataset_remove_row(netsnmp_table_data_set *table,
00193 netsnmp_table_row *row)
00194 {
00195 if (!table)
00196 return;
00197
00198 netsnmp_table_data_remove_and_delete_row(table->table, row);
00199 }
00200
00202 NETSNMP_INLINE void
00203 netsnmp_table_dataset_remove_and_delete_row(netsnmp_table_data_set *table,
00204 netsnmp_table_row *row)
00205 {
00206 netsnmp_table_data_set_storage *data;
00207
00208 if (!table)
00209 return;
00210
00211 data = (netsnmp_table_data_set_storage *)
00212 netsnmp_table_data_remove_and_delete_row(table->table, row);
00213
00214 netsnmp_table_dataset_delete_all_data(data);
00215 }
00216
00217
00218
00219
00220
00221
00222
00224 netsnmp_table_row *
00225 netsnmp_table_data_set_create_row_from_defaults
00226 (netsnmp_table_data_set_storage *defrow)
00227 {
00228 netsnmp_table_row *row;
00229 row = netsnmp_create_table_data_row();
00230 if (!row)
00231 return NULL;
00232 for (; defrow; defrow = defrow->next) {
00233 netsnmp_set_row_column(row, defrow->column, defrow->type,
00234 defrow->data.voidp, defrow->data_len);
00235 if (defrow->writable)
00236 netsnmp_mark_row_column_writable(row, defrow->column, 1);
00237
00238 }
00239 return row;
00240 }
00241
00251 int
00252 netsnmp_table_set_add_default_row(netsnmp_table_data_set *table_set,
00253 unsigned int column,
00254 int type, int writable,
00255 void *default_value,
00256 size_t default_value_len)
00257 {
00258 netsnmp_table_data_set_storage *new_col, *ptr, *pptr;
00259
00260 if (!table_set)
00261 return SNMPERR_GENERR;
00262
00263
00264
00265
00266 new_col =
00267 netsnmp_table_data_set_find_column(table_set->default_row, column);
00268 if (new_col != NULL) {
00269 if (new_col->type == type && new_col->writable == writable)
00270 return SNMPERR_SUCCESS;
00271 return SNMPERR_GENERR;
00272 }
00273
00274 new_col = SNMP_MALLOC_TYPEDEF(netsnmp_table_data_set_storage);
00275 new_col->type = type;
00276 new_col->writable = writable;
00277 new_col->column = column;
00278 if (default_value) {
00279 memdup((u_char **) & (new_col->data.voidp),
00280 (u_char *) default_value, default_value_len);
00281 new_col->data_len = default_value_len;
00282 }
00283 if (table_set->default_row == NULL)
00284 table_set->default_row = new_col;
00285 else {
00286
00287 for (ptr = table_set->default_row, pptr = NULL;
00288 ptr;
00289 pptr = ptr, ptr = ptr->next) {
00290 if (ptr->column > column) {
00291 new_col->next = ptr;
00292 if (pptr)
00293 pptr->next = new_col;
00294 else
00295 table_set->default_row = new_col;
00296 return SNMPERR_SUCCESS;
00297 }
00298 }
00299 if (pptr)
00300 pptr->next = new_col;
00301 else
00302 snmp_log(LOG_ERR,"Shouldn't have gotten here: table_dataset/add_row");
00303 }
00304 return SNMPERR_SUCCESS;
00305 }
00306
00311 void
00312 #if HAVE_STDARG_H
00313 netsnmp_table_set_multi_add_default_row(netsnmp_table_data_set *tset, ...)
00314 #else
00315 netsnmp_table_set_multi_add_default_row(va_dcl
00316 )
00317 va_dcl
00318 #endif
00319 {
00320 va_list debugargs;
00321 unsigned int column;
00322 int type, writable;
00323 void *data;
00324 size_t data_len;
00325
00326 #if HAVE_STDARG_H
00327 va_start(debugargs, tset);
00328 #else
00329 netsnmp_table_data_set *tset;
00330
00331 va_start(debugargs);
00332 tset = va_arg(debugargs, netsnmp_table_data_set *);
00333 #endif
00334
00335 while ((column = va_arg(debugargs, unsigned int)) != 0) {
00336 type = va_arg(debugargs, int);
00337 writable = va_arg(debugargs, int);
00338 data = va_arg(debugargs, void *);
00339 data_len = va_arg(debugargs, size_t);
00340 netsnmp_table_set_add_default_row(tset, column, type, writable,
00341 data, data_len);
00342 }
00343
00344 va_end(debugargs);
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00355 netsnmp_mib_handler *
00356 netsnmp_get_table_data_set_handler(netsnmp_table_data_set *data_set)
00357 {
00358 netsnmp_mib_handler *ret = NULL;
00359
00360 if (!data_set) {
00361 snmp_log(LOG_INFO,
00362 "netsnmp_get_table_data_set_handler(NULL) called\n");
00363 return NULL;
00364 }
00365
00366 ret =
00367 netsnmp_create_handler(TABLE_DATA_SET_NAME,
00368 netsnmp_table_data_set_helper_handler);
00369 if (ret) {
00370 ret->flags |= MIB_HANDLER_AUTO_NEXT;
00371 ret->myvoid = (void *) data_set;
00372 }
00373 return ret;
00374 }
00375
00381 int
00382 netsnmp_register_table_data_set(netsnmp_handler_registration *reginfo,
00383 netsnmp_table_data_set *data_set,
00384 netsnmp_table_registration_info *table_info)
00385 {
00386 if (NULL == table_info) {
00387
00388
00389
00390 table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
00391 }
00392
00393 if (NULL == table_info->indexes && data_set->table->indexes_template) {
00394
00395
00396
00397 table_info->indexes =
00398 snmp_clone_varbind(data_set->table->indexes_template);
00399 }
00400
00401 if ((!table_info->min_column || !table_info->max_column) &&
00402 (data_set->default_row)) {
00403
00404
00405
00406 unsigned int mincol = 0xffffffff, maxcol = 0;
00407 netsnmp_table_data_set_storage *row;
00408
00409 for (row = data_set->default_row; row; row = row->next) {
00410 mincol = SNMP_MIN(mincol, row->column);
00411 maxcol = SNMP_MAX(maxcol, row->column);
00412 }
00413 if (!table_info->min_column)
00414 table_info->min_column = mincol;
00415 if (!table_info->max_column)
00416 table_info->max_column = maxcol;
00417 }
00418
00419 netsnmp_inject_handler(reginfo,
00420 netsnmp_get_table_data_set_handler(data_set));
00421 return netsnmp_register_table_data(reginfo, data_set->table,
00422 table_info);
00423 }
00424
00425 newrow_stash *
00426 netsnmp_table_data_set_create_newrowstash
00427 (netsnmp_table_data_set *datatable,
00428 netsnmp_table_request_info *table_info)
00429 {
00430 newrow_stash *newrowstash = NULL;
00431 netsnmp_table_row *newrow = NULL;
00432
00433 newrowstash = SNMP_MALLOC_TYPEDEF(newrow_stash);
00434 newrowstash->created = 1;
00435 newrow = netsnmp_table_data_set_create_row_from_defaults
00436 (datatable->default_row);
00437 newrow->indexes = snmp_clone_varbind(table_info->indexes);
00438 newrowstash->newrow = newrow;
00439
00440 return newrowstash;
00441 }
00442
00443
00444
00445 int
00446 netsnmp_table_data_set_helper_handler(netsnmp_mib_handler *handler,
00447 netsnmp_handler_registration
00448 *reginfo,
00449 netsnmp_agent_request_info *reqinfo,
00450 netsnmp_request_info *requests)
00451 {
00452 netsnmp_table_data_set_storage *data = NULL;
00453 newrow_stash *newrowstash = NULL;
00454 netsnmp_table_row *row, *newrow = NULL;
00455 netsnmp_table_request_info *table_info;
00456 netsnmp_request_info *request;
00457 oid *suffix;
00458 size_t suffix_len;
00459 netsnmp_oid_stash_node **stashp = NULL;
00460
00461 if (!handler)
00462 return SNMPERR_GENERR;
00463
00464 DEBUGMSGTL(("netsnmp_table_data_set", "handler starting\n"));
00465 for (request = requests; request; request = request->next) {
00466 netsnmp_table_data_set *datatable =
00467 (netsnmp_table_data_set *) handler->myvoid;
00468 if (request->processed)
00469 continue;
00470
00471
00472
00473
00474 row = netsnmp_extract_table_row(request);
00475 table_info = netsnmp_extract_table_info(request);
00476 suffix = requests->requestvb->name + reginfo->rootoid_len + 2;
00477 suffix_len = requests->requestvb->name_length -
00478 (reginfo->rootoid_len + 2);
00479
00480 if (MODE_IS_SET(reqinfo->mode)) {
00481
00482 char buf[256];
00483 int rc;
00484 size_t len;
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 rc = snprintf(buf, sizeof(buf), "dataset_row_stash:%s:",
00495 datatable->table->name);
00496 if ((-1 == rc) || (rc >= sizeof(buf))) {
00497 snmp_log(LOG_ERR,"%s handler name too long\n",
00498 datatable->table->name);
00499 netsnmp_set_request_error(reqinfo, request,
00500 SNMP_ERR_GENERR);
00501 continue;
00502 }
00503 len = sizeof(buf) - rc;
00504 rc = snprint_objid(&buf[rc], len, table_info->index_oid,
00505 table_info->index_oid_len);
00506 if (-1 == rc) {
00507 snmp_log(LOG_ERR,"%s oid or name too long\n",
00508 datatable->table->name);
00509 netsnmp_set_request_error(reqinfo, request,
00510 SNMP_ERR_GENERR);
00511 continue;
00512 }
00513 stashp = (netsnmp_oid_stash_node **)
00514 netsnmp_table_get_or_create_row_stash(reqinfo, buf);
00515
00516 newrowstash
00517 = netsnmp_oid_stash_get_data(*stashp, suffix, suffix_len);
00518
00519 if (!newrowstash) {
00520 if (!row) {
00521 if (datatable->allow_creation) {
00522
00523
00524
00525 newrowstash =
00526 netsnmp_table_data_set_create_newrowstash(
00527 datatable, table_info);
00528 newrow = newrowstash->newrow;
00529 } else if (datatable->rowstatus_column == 0) {
00530
00531
00532
00533
00534
00535
00536 netsnmp_set_request_error(reqinfo, request,
00537 SNMP_ERR_NOCREATION);
00538 continue;
00539 }
00540 } else {
00541
00542
00543
00544 newrowstash = SNMP_MALLOC_TYPEDEF(newrow_stash);
00545 newrow = netsnmp_table_data_set_clone_row(row);
00546 newrowstash->newrow = newrow;
00547 }
00548 netsnmp_oid_stash_add_data(stashp, suffix, suffix_len,
00549 newrowstash);
00550 } else {
00551 newrow = newrowstash->newrow;
00552 }
00553
00554
00555
00556
00557 if (reqinfo->mode == MODE_SET_RESERVE1 ||
00558 reqinfo->mode == MODE_SET_RESERVE2)
00559 row = newrow;
00560 }
00561
00562 if (row)
00563 data = (netsnmp_table_data_set_storage *) row->data;
00564
00565 if (!row || !table_info || !data) {
00566 if (!MODE_IS_SET(reqinfo->mode)) {
00567 netsnmp_set_request_error(reqinfo, request,
00568 SNMP_NOSUCHINSTANCE);
00569 continue;
00570 }
00571 }
00572
00573 data =
00574 netsnmp_table_data_set_find_column(data, table_info->colnum);
00575
00576 switch (reqinfo->mode) {
00577 case MODE_GET:
00578 case MODE_GETNEXT:
00579 case MODE_GETBULK:
00580 if (data && data->data.voidp)
00581 netsnmp_table_data_build_result(reginfo, reqinfo, request,
00582 row,
00583 table_info->colnum,
00584 data->type,
00585 data->data.voidp,
00586 data->data_len);
00587 break;
00588
00589 case MODE_SET_RESERVE1:
00590 if (data) {
00591
00592
00593
00594 if (!data->writable) {
00595 netsnmp_set_request_error(reqinfo, request,
00596 SNMP_ERR_NOTWRITABLE);
00597 } else if (request->requestvb->type != data->type) {
00598 netsnmp_set_request_error(reqinfo, request,
00599 SNMP_ERR_WRONGTYPE);
00600 }
00601 } else if (datatable->rowstatus_column == table_info->colnum) {
00602
00603
00604
00605
00606
00607 switch (*(request->requestvb->val.integer)) {
00608 case RS_CREATEANDGO:
00609 case RS_CREATEANDWAIT:
00610 newrowstash =
00611 netsnmp_table_data_set_create_newrowstash(
00612 datatable, table_info);
00613 newrow = newrowstash->newrow;
00614 row = newrow;
00615 netsnmp_oid_stash_add_data(stashp, suffix, suffix_len,
00616 newrowstash);
00617 }
00618 }
00619 break;
00620
00621 case MODE_SET_RESERVE2:
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 if (data && data->writable == 0) {
00636 netsnmp_set_request_error(reqinfo, request,
00637 SNMP_ERR_NOTWRITABLE);
00638 continue;
00639 }
00640 if (datatable->rowstatus_column == table_info->colnum) {
00641 switch (*(request->requestvb->val.integer)) {
00642 case RS_ACTIVE:
00643 case RS_NOTINSERVICE:
00644
00645
00646
00647 if (!newrowstash || newrowstash->created) {
00648 netsnmp_set_request_error(reqinfo, request,
00649 SNMP_ERR_INCONSISTENTVALUE);
00650 continue;
00651 }
00652 break;
00653
00654 case RS_CREATEANDGO:
00655 case RS_CREATEANDWAIT:
00656
00657
00658
00659 if (!(newrowstash && newrowstash->created)) {
00660 netsnmp_set_request_error(reqinfo, request,
00661 SNMP_ERR_INCONSISTENTVALUE);
00662 continue;
00663 }
00664 break;
00665
00666 case RS_DESTROY:
00667
00668
00669
00670 break;
00671
00672 case RS_NOTREADY:
00673 default:
00674
00675
00676
00677 netsnmp_set_request_error(reqinfo, request,
00678 SNMP_ERR_WRONGVALUE);
00679 continue;
00680 }
00681 }
00682 if (!data ) {
00683 netsnmp_set_request_error(reqinfo, request,
00684 SNMP_ERR_NOCREATION);
00685 continue;
00686 }
00687
00688
00689
00690
00691 SNMP_FREE(data->data.string);
00692 data->data.string =
00693 netsnmp_strdup_and_null(request->requestvb->val.string,
00694 request->requestvb->val_len);
00695 if (!data->data.string) {
00696 netsnmp_set_request_error(reqinfo, requests,
00697 SNMP_ERR_RESOURCEUNAVAILABLE);
00698 }
00699 data->data_len = request->requestvb->val_len;
00700
00701 if (datatable->rowstatus_column == table_info->colnum) {
00702 switch (*(request->requestvb->val.integer)) {
00703 case RS_CREATEANDGO:
00704
00705
00706
00707 *(data->data.integer) = RS_ACTIVE;
00708 break;
00709
00710 case RS_CREATEANDWAIT:
00711
00712
00713
00714 *(data->data.integer) = RS_NOTINSERVICE;
00715 break;
00716
00717 case RS_DESTROY:
00718 newrowstash->deleted = 1;
00719 break;
00720 }
00721 }
00722 break;
00723
00724 case MODE_SET_ACTION:
00725
00726
00727
00728
00729
00730 if (newrowstash->state != STATE_ACTION) {
00731 newrowstash->state = STATE_ACTION;
00732 if (newrowstash->created) {
00733 netsnmp_table_dataset_add_row(datatable, newrow);
00734 } else {
00735 netsnmp_table_dataset_replace_row(datatable,
00736 row, newrow);
00737 }
00738 }
00739
00740
00741
00742
00743
00744 if (newrowstash->created) {
00745 netsnmp_request_add_list_data(request,
00746 netsnmp_create_data_list(TABLE_DATA_NAME,
00747 newrow, NULL));
00748 }
00749 break;
00750
00751 case MODE_SET_UNDO:
00752
00753
00754
00755 if (newrowstash->state != STATE_UNDO) {
00756 newrowstash->state = STATE_UNDO;
00757 if (newrowstash->created) {
00758 netsnmp_table_dataset_remove_and_delete_row(datatable, newrow);
00759 } else {
00760 netsnmp_table_dataset_replace_row(datatable,
00761 newrow, row);
00762 netsnmp_table_dataset_delete_row(newrow);
00763 }
00764 newrow = NULL;
00765 }
00766 break;
00767
00768 case MODE_SET_COMMIT:
00769 if (newrowstash->state != STATE_COMMIT) {
00770 newrowstash->state = STATE_COMMIT;
00771 if (!newrowstash->created) {
00772 netsnmp_request_info *req;
00773 netsnmp_table_dataset_delete_row(row);
00774
00775
00776 for (req = requests; req; req=req->next) {
00777
00778
00779
00780
00781
00782 if ((netsnmp_table_row *) netsnmp_extract_table_row(req) == row) {
00783 netsnmp_request_remove_list_data(req, TABLE_DATA_ROW);
00784 netsnmp_request_add_list_data(req,
00785 netsnmp_create_data_list(TABLE_DATA_ROW, newrow, NULL));
00786 }
00787 }
00788
00789 row = NULL;
00790 }
00791 if (newrowstash->deleted) {
00792 netsnmp_table_dataset_remove_and_delete_row(datatable, newrow);
00793 newrow = NULL;
00794 }
00795 }
00796 break;
00797
00798 case MODE_SET_FREE:
00799 if (newrowstash && newrowstash->state != STATE_FREE) {
00800 newrowstash->state = STATE_FREE;
00801 netsnmp_table_dataset_delete_row(newrow);
00802 newrow = NULL;
00803 }
00804 break;
00805 }
00806 }
00807
00808
00809 return SNMP_ERR_NOERROR;
00810 }
00811
00815 NETSNMP_INLINE netsnmp_table_data_set *
00816 netsnmp_extract_table_data_set(netsnmp_request_info *request)
00817 {
00818 return (netsnmp_table_data_set *)
00819 netsnmp_request_get_list_data(request, TABLE_DATA_SET_NAME);
00820 }
00821
00825 netsnmp_table_data_set_storage *
00826 netsnmp_extract_table_data_set_column(netsnmp_request_info *request,
00827 unsigned int column)
00828 {
00829 netsnmp_table_data_set_storage *data =
00830 netsnmp_extract_table_row_data( request );
00831 if (data) {
00832 data = netsnmp_table_data_set_find_column(data, column);
00833 }
00834 return data;
00835 }
00836
00837
00838
00839
00840
00841
00842
00843
00852 void
00853 netsnmp_register_auto_data_table(netsnmp_table_data_set *table_set,
00854 char *registration_name)
00855 {
00856 data_set_tables *tables;
00857 tables = SNMP_MALLOC_TYPEDEF(data_set_tables);
00858 if (!tables)
00859 return;
00860 tables->table_set = table_set;
00861 if (!registration_name) {
00862 registration_name = table_set->table->name;
00863 }
00864 netsnmp_add_list_data(&auto_tables, netsnmp_create_data_list(registration_name, tables, NULL));
00865 }
00866
00867 #ifndef DISABLE_MIB_LOADING
00868 static void
00869 _table_set_add_indexes(netsnmp_table_data_set *table_set, struct tree *tp)
00870 {
00871 oid name[MAX_OID_LEN];
00872 size_t name_length = MAX_OID_LEN;
00873 struct index_list *index;
00874 struct tree *indexnode;
00875 u_char type;
00876
00877
00878
00879
00880 for (index = tp->indexes; index; index = index->next) {
00881 if (!snmp_parse_oid(index->ilabel, name, &name_length) ||
00882 (NULL ==
00883 (indexnode = get_tree(name, name_length, get_tree_head())))) {
00884 config_pwarn("can't instatiate table since "
00885 "I don't know anything about one index");
00886 snmp_log(LOG_WARNING, " index %s not found in tree\n",
00887 index->ilabel);
00888 return;
00889 }
00890
00891 type = mib_to_asn_type(indexnode->type);
00892 if (type == (u_char) - 1) {
00893 config_pwarn("unknown index type");
00894 return;
00895 }
00896
00897
00898
00899
00900 if ((index->isimplied) ||
00901 ((TYPE_OCTETSTR == indexnode->type) &&
00902 (NULL != indexnode->ranges) &&
00903 (NULL == indexnode->ranges->next) &&
00904 (indexnode->ranges->high ==
00905 indexnode->ranges->low)))
00906 type |= ASN_PRIVATE;
00907
00908 DEBUGMSGTL(("table_set_add_table",
00909 "adding default index of type %d\n", type));
00910 netsnmp_table_dataset_add_index(table_set, type);
00911 }
00912 }
00914 void
00915 netsnmp_config_parse_table_set(const char *token, char *line)
00916 {
00917 oid table_name[MAX_OID_LEN];
00918 size_t table_name_length = MAX_OID_LEN;
00919 struct tree *tp;
00920 netsnmp_table_data_set *table_set;
00921 data_set_tables *tables;
00922 unsigned int mincol = 0xffffff, maxcol = 0;
00923 char *pos;
00924
00925
00926
00927
00928 DEBUGMSGTL(("9:table_set_add_table", "processing '%s'\n", line));
00929 if (NULL != (pos = strchr(line,' '))) {
00930 config_pwarn("ignoring extra tokens on line");
00931 snmp_log(LOG_WARNING," ignoring '%s'\n", pos);
00932 *pos = '\0';
00933 }
00934
00935
00936
00937
00938 tables = (data_set_tables *) netsnmp_get_list_data(auto_tables, line);
00939 if (NULL != tables) {
00940 config_pwarn("duplicate table definition");
00941 return;
00942 }
00943
00944
00945
00946
00947 if (!snmp_parse_oid(line, table_name, &table_name_length)) {
00948 config_pwarn
00949 ("can't instatiate table since I can't parse the table name");
00950 return;
00951 }
00952 if(NULL == (tp = get_tree(table_name, table_name_length,
00953 get_tree_head()))) {
00954 config_pwarn("can't instatiate table since "
00955 "I can't find mib information about it");
00956 return;
00957 }
00958
00959 if (NULL == (tp = tp->child_list) || NULL == tp->child_list) {
00960 config_pwarn("can't instatiate table since it doesn't appear to be "
00961 "a proper table (no children)");
00962 return;
00963 }
00964
00965 table_set = netsnmp_create_table_data_set(line);
00966
00967
00968
00969
00970 if (NULL != tp->augments) {
00971 oid name[MAX_OID_LEN];
00972 size_t name_length = MAX_OID_LEN;
00973 struct tree *tp2;
00974
00975 if (!snmp_parse_oid(tp->augments, name, &name_length)) {
00976 config_pwarn("I can't parse the augment tabel name");
00977 snmp_log(LOG_WARNING, " can't parse %s\n", tp->augments);
00978 return;
00979 }
00980 if(NULL == (tp2 = get_tree(name, name_length, get_tree_head()))) {
00981 config_pwarn("can't instatiate table since "
00982 "I can't find mib information about augment table");
00983 snmp_log(LOG_WARNING, " table %s not found in tree\n",
00984 tp->augments);
00985 return;
00986 }
00987 _table_set_add_indexes(table_set, tp2);
00988 }
00989
00990 _table_set_add_indexes(table_set, tp);
00991
00992
00993
00994
00995 for (tp = tp->child_list; tp; tp = tp->next_peer) {
00996 int canwrite = 0;
00997 u_char type;
00998 type = mib_to_asn_type(tp->type);
00999 if (type == (u_char) - 1) {
01000 config_pwarn("unknown column type");
01001 return;
01002 }
01003
01004 DEBUGMSGTL(("table_set_add_table",
01005 "adding column %s(%d) of type %d (access %d)\n",
01006 tp->label, tp->subid, type, tp->access));
01007
01008 switch (tp->access) {
01009 case MIB_ACCESS_CREATE:
01010 table_set->allow_creation = 1;
01011 case MIB_ACCESS_READWRITE:
01012 case MIB_ACCESS_WRITEONLY:
01013 canwrite = 1;
01014 case MIB_ACCESS_READONLY:
01015 DEBUGMSGTL(("table_set_add_table",
01016 "adding column %d of type %d\n", tp->subid, type));
01017 netsnmp_table_set_add_default_row(table_set, tp->subid, type,
01018 canwrite, NULL, 0);
01019 mincol = SNMP_MIN(mincol, tp->subid);
01020 maxcol = SNMP_MAX(maxcol, tp->subid);
01021 break;
01022
01023 case MIB_ACCESS_NOACCESS:
01024 case MIB_ACCESS_NOTIFY:
01025 break;
01026
01027 default:
01028 config_pwarn("unknown column access type");
01029 break;
01030 }
01031 }
01032
01033
01034
01035
01036 netsnmp_register_table_data_set(netsnmp_create_handler_registration
01037 (line, NULL, table_name,
01038 table_name_length,
01039 HANDLER_CAN_RWRITE), table_set, NULL);
01040
01041 netsnmp_register_auto_data_table(table_set, NULL);
01042 }
01043 #endif
01044
01046 void
01047 netsnmp_config_parse_add_row(const char *token, char *line)
01048 {
01049 char buf[SNMP_MAXBUF_MEDIUM];
01050 char tname[SNMP_MAXBUF_MEDIUM];
01051 size_t buf_size;
01052 int rc;
01053
01054 data_set_tables *tables;
01055 netsnmp_variable_list *vb;
01056 netsnmp_table_row *row;
01057 netsnmp_table_data_set_storage *dr;
01058
01059 line = copy_nword(line, tname, SNMP_MAXBUF_MEDIUM);
01060
01061 tables = (data_set_tables *) netsnmp_get_list_data(auto_tables, tname);
01062 if (!tables) {
01063 config_pwarn("Unknown table trying to add a row");
01064 return;
01065 }
01066
01067
01068
01069
01070 row = netsnmp_create_table_data_row();
01071
01072 for (vb = tables->table_set->table->indexes_template; vb;
01073 vb = vb->next_variable) {
01074 if (!line) {
01075 config_pwarn("missing an index value");
01076 return;
01077 }
01078
01079 DEBUGMSGTL(("table_set_add_row", "adding index of type %d\n",
01080 vb->type));
01081 buf_size = SNMP_MAXBUF_MEDIUM;
01082 line = read_config_read_memory(vb->type, line, buf, &buf_size);
01083 netsnmp_table_row_add_index(row, vb->type, buf, buf_size);
01084 }
01085
01086
01087
01088
01089 for (dr = tables->table_set->default_row; dr; dr = dr->next) {
01090 if (!line) {
01091 config_pwarn("missing a data value. "
01092 "All columns must be specified.");
01093 snmp_log(LOG_WARNING," can't find value for column %d\n",
01094 dr->column - 1);
01095 return;
01096 }
01097
01098 buf_size = SNMP_MAXBUF_MEDIUM;
01099 line = read_config_read_memory(dr->type, line, buf, &buf_size);
01100 DEBUGMSGTL(("table_set_add_row",
01101 "adding data at column %d of type %d\n", dr->column,
01102 dr->type));
01103 netsnmp_set_row_column(row, dr->column, dr->type, buf, buf_size);
01104 if (dr->writable)
01105 netsnmp_mark_row_column_writable(row, dr->column, 1);
01106 }
01107 rc = netsnmp_table_data_add_row(tables->table_set->table, row);
01108 if (SNMPERR_SUCCESS != rc) {
01109 config_pwarn("error adding table row");
01110 }
01111 if (NULL != line) {
01112 config_pwarn("extra data value. Too many columns specified.");
01113 snmp_log(LOG_WARNING," extra data '%s'\n", line);
01114 }
01115 }
01116
01117
01118
01119
01120
01121
01122
01123
01125 netsnmp_table_row *
01126 netsnmp_table_data_set_get_first_row(netsnmp_table_data_set *table)
01127 {
01128 return netsnmp_table_data_get_first_row(table->table);
01129 }
01130
01132 netsnmp_table_row *
01133 netsnmp_table_data_set_get_next_row(netsnmp_table_data_set *table,
01134 netsnmp_table_row *row)
01135 {
01136 return netsnmp_table_data_get_next_row(table->table, row);
01137 }
01138
01139 int
01140 netsnmp_table_set_num_rows(netsnmp_table_data_set *table)
01141 {
01142 if (!table)
01143 return 0;
01144 return netsnmp_table_data_num_rows(table->table);
01145 }
01146
01147
01148
01149
01150
01151
01152
01156 netsnmp_table_data_set_storage *
01157 netsnmp_table_data_set_find_column(netsnmp_table_data_set_storage *start,
01158 unsigned int column)
01159 {
01160 while (start && start->column != column)
01161 start = start->next;
01162 return start;
01163 }
01164
01168 int
01169 netsnmp_mark_row_column_writable(netsnmp_table_row *row, int column,
01170 int writable)
01171 {
01172 netsnmp_table_data_set_storage *data;
01173
01174 if (!row)
01175 return SNMPERR_GENERR;
01176
01177 data = (netsnmp_table_data_set_storage *) row->data;
01178 data = netsnmp_table_data_set_find_column(data, column);
01179
01180 if (!data) {
01181
01182
01183
01184 data = SNMP_MALLOC_TYPEDEF(netsnmp_table_data_set_storage);
01185 if (!data) {
01186 snmp_log(LOG_CRIT, "no memory in netsnmp_set_row_column");
01187 return SNMPERR_MALLOC;
01188 }
01189 data->column = column;
01190 data->writable = writable;
01191 data->next = row->data;
01192 row->data = data;
01193 } else {
01194 data->writable = writable;
01195 }
01196 return SNMPERR_SUCCESS;
01197 }
01198
01203 int
01204 netsnmp_set_row_column(netsnmp_table_row *row, unsigned int column,
01205 int type, const char *value, size_t value_len)
01206 {
01207 netsnmp_table_data_set_storage *data;
01208
01209 if (!row)
01210 return SNMPERR_GENERR;
01211
01212 data = (netsnmp_table_data_set_storage *) row->data;
01213 data = netsnmp_table_data_set_find_column(data, column);
01214
01215 if (!data) {
01216
01217
01218
01219 data = SNMP_MALLOC_TYPEDEF(netsnmp_table_data_set_storage);
01220 if (!data) {
01221 snmp_log(LOG_CRIT, "no memory in netsnmp_set_row_column");
01222 return SNMPERR_MALLOC;
01223 }
01224
01225 data->column = column;
01226 data->type = type;
01227 data->next = row->data;
01228 row->data = data;
01229 }
01230
01231 if (value) {
01232 if (data->type != type)
01233 return SNMPERR_GENERR;
01234
01235 SNMP_FREE(data->data.voidp);
01236 if (value_len) {
01237 if (memdup(&data->data.string, value, (value_len)) !=
01238 SNMPERR_SUCCESS) {
01239 snmp_log(LOG_CRIT, "no memory in netsnmp_set_row_column");
01240 return SNMPERR_MALLOC;
01241 }
01242 } else {
01243 data->data.string = malloc(1);
01244 }
01245 data->data_len = value_len;
01246 }
01247 return SNMPERR_SUCCESS;
01248 }
01249
01250
01251
01252
01253
01254
01255
01257 NETSNMP_INLINE void
01258 netsnmp_table_dataset_add_index(netsnmp_table_data_set *table, u_char type)
01259 {
01260 if (!table)
01261 return;
01262 netsnmp_table_data_add_index(table->table, type);
01263 }
01264
01267 void
01268 #if HAVE_STDARG_H
01269 netsnmp_table_set_add_indexes(netsnmp_table_data_set *tset,
01270 ...)
01271 #else
01272 netsnmp_table_set_add_indexes(va_alist)
01273 va_dcl
01274 #endif
01275 {
01276 va_list debugargs;
01277 int type;
01278
01279 #if HAVE_STDARG_H
01280 va_start(debugargs, tset);
01281 #else
01282 netsnmp_table_data_set *tset;
01283
01284 va_start(debugargs);
01285 tset = va_arg(debugargs, netsnmp_table_data_set *);
01286 #endif
01287
01288 while ((type = va_arg(debugargs, int)) != 0) {
01289 netsnmp_table_dataset_add_index(tset, (u_char)type);
01290 }
01291
01292 va_end(debugargs);
01293 }
01294