📄 table_dataset.c
字号:
#include <net-snmp/net-snmp-config.h>#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#include <net-snmp/net-snmp-includes.h>#include <net-snmp/agent/net-snmp-agent-includes.h>#if HAVE_DMALLOC_H#include <dmalloc.h>#endifstatic netsnmp_data_list *auto_tables;typedef struct data_set_tables_s { netsnmp_table_data_set *table_set;} data_set_tables;typedef struct data_set_cache_s { void *data; size_t data_len;} data_set_cache;#define STATE_ACTION 1#define STATE_COMMIT 2#define STATE_UNDO 3#define STATE_FREE 4typedef struct newrow_stash_s { netsnmp_table_row *newrow; int state; int created; int deleted;} newrow_stash;/** @defgroup table_dataset table_dataset: Helps you implement a table with automatted storage. * @ingroup table_data * * This handler helps you implement a table where all the data is * expected to be stored within the agent itself and not in some * external storage location. It handles all MIB requests including * GETs, GETNEXTs and SETs. It's possible to simply create a table * without actually ever defining a handler to be called when SNMP * requests come in. To use the data, you can either attach a * sub-handler that merely uses/manipulates the data further when * requests come in, or you can loop through it externally when it's * actually needed. This handler is most useful in cases where a * table is holding configuration data for something which gets * triggered via another event. * * NOTE NOTE NOTE: This helper isn't complete and is likely to change * somewhat over time. Specifically, the way it stores data * internally may change drastically. * * @{ */voidnetsnmp_init_table_dataset(void) {#ifndef DISABLE_MIB_LOADING register_app_config_handler("table", netsnmp_config_parse_table_set, NULL, "tableoid");#endif /* DISABLE_MIB_LOADING */ register_app_config_handler("add_row", netsnmp_config_parse_add_row, NULL, "table_name indexes... values...");}/** Create a netsnmp_table_data_set structure given a table_data definition */netsnmp_table_data_set *netsnmp_create_table_data_set(const char *table_name){ netsnmp_table_data_set *table_set = SNMP_MALLOC_TYPEDEF(netsnmp_table_data_set); if (!table_set) return NULL; table_set->table = netsnmp_create_table_data(table_name); return table_set;}/** Given a netsnmp_table_data_set definition, create a handler for it */netsnmp_mib_handler *netsnmp_get_table_data_set_handler(netsnmp_table_data_set *data_set){ netsnmp_mib_handler *ret = NULL; if (!data_set) { snmp_log(LOG_INFO, "netsnmp_get_table_data_set_handler(NULL) called\n"); return NULL; } ret = netsnmp_create_handler(TABLE_DATA_SET_NAME, netsnmp_table_data_set_helper_handler); if (ret) { ret->flags |= MIB_HANDLER_AUTO_NEXT; ret->myvoid = (void *) data_set; } return ret;}/** register a given data_set at a given oid (specified in the netsnmp_handler_registration pointer). The reginfo->handler->access_method *may* be null if the call doesn't ever want to be called for SNMP operations.*/intnetsnmp_register_table_data_set(netsnmp_handler_registration *reginfo, netsnmp_table_data_set *data_set, netsnmp_table_registration_info *table_info){ if (NULL == table_info) { /* * allocate the table if one wasn't allocated */ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); } if (NULL == table_info->indexes && data_set->table->indexes_template) { /* * copy the indexes in */ table_info->indexes = snmp_clone_varbind(data_set->table->indexes_template); } if ((!table_info->min_column || !table_info->max_column) && (data_set->default_row)) { /* * determine min/max columns */ unsigned int mincol = 0xffffffff, maxcol = 0; netsnmp_table_data_set_storage *row; for (row = data_set->default_row; row; row = row->next) { mincol = SNMP_MIN(mincol, row->column); maxcol = SNMP_MAX(maxcol, row->column); } if (!table_info->min_column) table_info->min_column = mincol; if (!table_info->max_column) table_info->max_column = maxcol; } netsnmp_inject_handler(reginfo, netsnmp_get_table_data_set_handler(data_set)); return netsnmp_register_table_data(reginfo, data_set->table, table_info);}/** Finds a column within a given storage set, given the pointer to the start of the storage set list.*/netsnmp_table_data_set_storage *netsnmp_table_data_set_find_column(netsnmp_table_data_set_storage *start, unsigned int column){ while (start && start->column != column) start = start->next; return start;}/** * extracts a netsnmp_table_data_set pointer from a given request */netsnmp_table_data_set_storage *netsnmp_extract_table_data_set_column(netsnmp_request_info *request, unsigned int column){ netsnmp_table_data_set_storage *data = netsnmp_extract_table_row_data( request ); if (data) { data = netsnmp_table_data_set_find_column(data, column); } return data;}/** * extracts a netsnmp_table_data_set pointer from a given request */NETSNMP_INLINE netsnmp_table_data_set *netsnmp_extract_table_data_set(netsnmp_request_info *request){ return (netsnmp_table_data_set *) netsnmp_request_get_list_data(request, TABLE_DATA_SET_NAME);}/** * marks a given column in a row as writable or not. */intnetsnmp_mark_row_column_writable(netsnmp_table_row *row, int column, int writable){ netsnmp_table_data_set_storage *data; if (!row) return SNMPERR_GENERR; data = (netsnmp_table_data_set_storage *) row->data; data = netsnmp_table_data_set_find_column(data, column); if (!data) { /* * create it */ data = SNMP_MALLOC_TYPEDEF(netsnmp_table_data_set_storage); if (!data) { snmp_log(LOG_CRIT, "no memory in netsnmp_set_row_column"); return SNMPERR_MALLOC; } data->column = column; data->writable = writable; data->next = row->data; row->data = data; } else { data->writable = writable; } return SNMPERR_SUCCESS;}/** * sets a given column in a row with data given a type, value, and * length. Data is memdup'ed by the function. */intnetsnmp_set_row_column(netsnmp_table_row *row, unsigned int column, int type, const char *value, size_t value_len){ netsnmp_table_data_set_storage *data; if (!row) return SNMPERR_GENERR; data = (netsnmp_table_data_set_storage *) row->data; data = netsnmp_table_data_set_find_column(data, column); if (!data) { /* * create it */ data = SNMP_MALLOC_TYPEDEF(netsnmp_table_data_set_storage); if (!data) { snmp_log(LOG_CRIT, "no memory in netsnmp_set_row_column"); return SNMPERR_MALLOC; } data->column = column; data->type = type; data->next = row->data; row->data = data; } if (value) { if (data->type != type) return SNMPERR_GENERR; SNMP_FREE(data->data.voidp); if (value_len) { if (memdup(&data->data.string, value, (value_len)) != SNMPERR_SUCCESS) { snmp_log(LOG_CRIT, "no memory in netsnmp_set_row_column"); return SNMPERR_MALLOC; } } else { data->data.string = malloc(1); } data->data_len = value_len; } return SNMPERR_SUCCESS;}/** adds a new default row to a table_set. * Arguments should be the table_set, column number, variable type and * finally a 1 if it is allowed to be writable, or a 0 if not. If the * default_value field is not NULL, it will be used to populate new * valuse in that column fro newly created rows. It is copied into the * storage template (free your calling argument). * * returns SNMPERR_SUCCESS or SNMPERR_FAILURE */intnetsnmp_table_set_add_default_row(netsnmp_table_data_set *table_set, unsigned int column, int type, int writable, void *default_value, size_t default_value_len){ netsnmp_table_data_set_storage *new_col, *ptr, *pptr; if (!table_set) return SNMPERR_GENERR; /* * double check */ new_col = netsnmp_table_data_set_find_column(table_set->default_row, column); if (new_col != NULL) { if (new_col->type == type && new_col->writable == writable) return SNMPERR_SUCCESS; return SNMPERR_GENERR; } new_col = SNMP_MALLOC_TYPEDEF(netsnmp_table_data_set_storage); new_col->type = type; new_col->writable = writable; new_col->column = column; if (default_value) { memdup((u_char **) & (new_col->data.voidp), (u_char *) default_value, default_value_len); new_col->data_len = default_value_len; } if (table_set->default_row == NULL) table_set->default_row = new_col; else { /* sort in order just because (needed for add_row support) */ for (ptr = table_set->default_row, pptr = NULL; ptr; pptr = ptr, ptr = ptr->next) { if (ptr->column > column) { new_col->next = ptr; if (pptr) pptr->next = new_col; else table_set->default_row = new_col; return SNMPERR_SUCCESS; } } if (pptr) pptr->next = new_col; else snmp_log(LOG_ERR,"Shouldn't have gotten here: table_dataset/add_row"); } return SNMPERR_SUCCESS;}/** clones a dataset row, including all data. */netsnmp_table_row *netsnmp_table_data_set_clone_row(netsnmp_table_row *row){ netsnmp_table_data_set_storage *data, **newrowdata; netsnmp_table_row *newrow; if (!row) return NULL; newrow = netsnmp_table_data_clone_row(row); if (!newrow) return NULL; data = (netsnmp_table_data_set_storage *) row->data; if (data) { for (newrowdata = (netsnmp_table_data_set_storage **) &(newrow->data); data; newrowdata = &((*newrowdata)->next), data = data->next) { memdup((u_char **) newrowdata, (u_char *) data, sizeof(netsnmp_table_data_set_storage)); if (!*newrowdata) { netsnmp_table_dataset_delete_row(newrow); return NULL; } if (data->data.voidp) { memdup((u_char **) & ((*newrowdata)->data.voidp), (u_char *) data->data.voidp, data->data_len); if (!(*newrowdata)->data.voidp) { netsnmp_table_dataset_delete_row(newrow); return NULL; } } } } return newrow;}/** creates a new row from an existing defined default set */netsnmp_table_row *netsnmp_table_data_set_create_row_from_defaults (netsnmp_table_data_set_storage *defrow){ netsnmp_table_row *row; row = netsnmp_create_table_data_row(); if (!row) return NULL; for (; defrow; defrow = defrow->next) { netsnmp_set_row_column(row, defrow->column, defrow->type, defrow->data.voidp, defrow->data_len); if (defrow->writable) netsnmp_mark_row_column_writable(row, defrow->column, 1); } return row;}newrow_stash *netsnmp_table_data_set_create_newrowstash (netsnmp_table_data_set *datatable, netsnmp_table_request_info *table_info)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -