--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/net-snmp/sun/sdk/demo/demo_module_5/demo_module_5.c Fri May 20 12:17:45 2011 +0530
@@ -0,0 +1,646 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ *
+ * U.S. Government Rights - Commercial software. Government users are subject to
+ * the Sun Microsystems, Inc. standard license agreement and applicable
+ * provisions of the FAR and its supplements.
+ *
+ *
+ * This distribution may include materials developed by third parties. Sun, Sun
+ * Microsystems, the Sun logo and Solaris are trademarks or registered
+ * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
+ */
+
+
+/*
+ * Note: this file originally auto-generated by mib2c using :
+ * mib2c.iterate.conf,v 1.1.1.1 2003/03/26 18:12:29 pcarroll Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "demo_module_5.h"
+#include <net-snmp/agent/agent_trap.h>
+
+/*
+ * MAXNAMELEN is the maximum permissible file name defined in param.h
+ */
+
+fileEntry *fileList = 0;
+char file1[MAXNAMELEN], file2[MAXNAMELEN], file3[MAXNAMELEN],
+ file4[MAXNAMELEN];
+
+
+
+/** Initialize the me5FileTable table by defining its contents and how it's structured */
+
+void
+initialize_table_me5FileTable(void)
+{
+ static oid me5FileTable_oid[] = {1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 4, 5, 2, 1};
+ netsnmp_table_registration_info *table_info;
+ netsnmp_handler_registration *my_handler;
+ netsnmp_iterator_info *iinfo;
+
+ /* create the table structure itself */
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
+
+ /*
+ * if your table is read only, it's easiest to change the
+ * HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY
+ */
+ my_handler = netsnmp_create_handler_registration("me5FileTable",
+ me5FileTable_handler,
+ me5FileTable_oid,
+ OID_LENGTH(me5FileTable_oid),
+ HANDLER_CAN_RWRITE);
+
+ if (!my_handler || !table_info || !iinfo) {
+ return; /* mallocs failed */
+ }
+
+ /***************************************************
+ * Setting up the table's definition
+ */
+
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_UNSIGNED, /* index: me5FileIndex */
+ 0);
+
+ table_info->min_column = 1;
+ table_info->max_column = 4;
+
+ /* iterator access routines */
+ iinfo->get_first_data_point = me5FileTable_get_first_data_point;
+ iinfo->get_next_data_point = me5FileTable_get_next_data_point;
+
+ iinfo->table_reginfo = table_info;
+
+ /***************************************************
+ * registering the table with the master agent
+ */
+
+ DEBUGMSGTL(("initialize_table_me5FileTable",
+ "Registering table me5FileTable as a table iterator\n"));
+ netsnmp_register_table_iterator(my_handler, iinfo);
+}
+
+
+/** Initializes the demo_module_5 module */
+
+
+void
+init_demo_module_5(void)
+{
+
+ /* here we initialize all the tables we're planning on supporting */
+
+
+ initialize_table_me5FileTable();
+
+
+ /*
+ * These are the default files that are monitored by the module if there
+ * is no persistent data (file names to be monitored). This is likely
+ * during the first running on the module, when the .conf file does not
+ * have any file related information.
+ */
+
+ strcpy(file1, "/etc/hosts");
+ strcpy(file2, "/etc/group");
+ strcpy(file3, "/etc/passwd");
+ strcpy(file4, "/etc/system");
+
+
+ /*
+ * Register for tokens from demo_module_5.conf file. The names of the
+ * tokens are demo5_file1,demo5_file2,demo5_file3,demo5_file4. The function
+ * demo5_load_tokens is called whenever these 4 tokens are encountered in
+ * demo_module_5.conf file.
+ */
+
+ register_config_handler(DEMO5_CONF_FILE, "demo5_file1",
+ demo5_load_tokens, NULL, NULL);
+
+ register_config_handler(DEMO5_CONF_FILE, "demo5_file2",
+ demo5_load_tokens, NULL, NULL);
+
+ register_config_handler(DEMO5_CONF_FILE, "demo5_file3",
+ demo5_load_tokens, NULL, NULL);
+
+ register_config_handler(DEMO5_CONF_FILE, "demo5_file4",
+ demo5_load_tokens, NULL, NULL);
+
+
+
+ /*
+ * Register for a callback when all the configuration files are read. The
+ * callback function here is demo5_post_read_config
+ */
+
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG,
+ demo5_post_read_config, NULL);
+
+
+}
+
+
+/** returns the first data point within the me5FileTable table data.
+
+ Set the my_loop_context variable to the first data point structure
+ of your choice (from which you can find the next one). This could
+ be anything from the first node in a linked list, to an integer
+ pointer containing the beginning of an array variable.
+
+ Set the my_data_context variable to something to be returned to
+ you later that will provide you with the data to return in a given
+ row. This could be the same pointer as what my_loop_context is
+ set to, or something different.
+
+ The put_index_data variable contains a list of snmp variable
+ bindings, one for each index in your table. Set the values of
+ each appropriately according to the data matching the first row
+ and return the put_index_data variable at the end of the function.
+*/
+
+
+netsnmp_variable_list *
+me5FileTable_get_first_data_point(void **my_loop_context, void **my_data_context,
+ netsnmp_variable_list * put_index_data,
+ netsnmp_iterator_info * mydata)
+{
+
+ netsnmp_variable_list *vptr;
+
+ fileEntry *firstFile = fileList;
+ if (!firstFile) {
+ return NULL;
+ }
+ *my_loop_context = firstFile;
+ *my_data_context = firstFile;
+
+
+ vptr = put_index_data;
+
+ snmp_set_var_value(vptr, (u_char *) & fileList->findex, sizeof(fileList->findex));
+ vptr = vptr->next_variable;
+
+ return put_index_data;
+}
+
+
+/** functionally the same as me5FileTable_get_first_data_point, but
+ my_loop_context has already been set to a previous value and should
+ be updated to the next in the list. For example, if it was a
+ linked list, you might want to cast it and the return
+ my_loop_context->next. The my_data_context pointer should be set
+ to something you need later and the indexes in put_index_data
+ updated again. */
+
+
+
+netsnmp_variable_list *
+me5FileTable_get_next_data_point(void **my_loop_context, void **my_data_context,
+ netsnmp_variable_list * put_index_data,
+ netsnmp_iterator_info * mydata)
+{
+
+ netsnmp_variable_list *vptr;
+ fileEntry *nextNode = (fileEntry *) * my_loop_context;
+ nextNode = nextNode->next;
+
+ if (!nextNode) {
+ return NULL;
+ }
+ *my_loop_context = nextNode;
+ *my_data_context = nextNode;
+
+ vptr = put_index_data;
+
+
+
+ snmp_set_var_value(vptr, (u_char *) & nextNode->findex,
+ sizeof(nextNode->findex));
+ vptr = vptr->next_variable;
+
+ return put_index_data;
+}
+
+
+/** handles requests for the me5FileTable table, if anything else needs to be done */
+
+int
+me5FileTable_handler(
+ netsnmp_mib_handler * handler,
+ netsnmp_handler_registration * reginfo,
+ netsnmp_agent_request_info * reqinfo,
+ netsnmp_request_info * requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *table_info;
+ netsnmp_variable_list *var;
+ fileEntry *data;
+ char *fileName = NULL;
+ char *undofn;
+ int len;
+
+ char filebuf[255];
+
+ for (request = requests; request; request = request->next) {
+
+ var = request->requestvb;
+ if (request->processed != 0)
+ continue;
+
+ /*
+ * the following extracts the my_data_context pointer set in the loop
+ * functions above. You can then use the results to help return data
+ * for the columns of the me5FileTable table in question
+ */
+
+ data = (fileEntry *) netsnmp_extract_iterator_context(request);
+ if (data == NULL) {
+ if (reqinfo->mode == MODE_GET) {
+ netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
+ } else {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ }
+ continue;
+ } else {
+ struct stat fAttrib;
+ if (stat(GetFileName(data->findex), &fAttrib) != -1) {
+ data->fileSize = fAttrib.st_size;
+ sprintf(data->filePerm, "%o", fAttrib.st_mode & 0777);
+ } else {
+ data->fileSize = 0;
+ sprintf(data->filePerm, "%d", -1);
+ }
+
+ }
+
+ /* extracts the information about the table from the request */
+ table_info = netsnmp_extract_table_info(request);
+ /* table_info->colnum contains the column number requested */
+ /*
+ * table_info->indexes contains a linked list of snmp variable
+ * bindings for the indexes of the table. Values in the list have
+ * been set corresponding to the indexes of the request
+ */
+
+ if (table_info == NULL) {
+ continue;
+ }
+ switch (reqinfo->mode) {
+ /*
+ * the table_iterator helper should change all GETNEXTs into GETs
+ * for you automatically, so you don't have to worry about the
+ * GETNEXT case. Only GETs and SETs need to be dealt with here
+ */
+ case MODE_GET:
+ switch (table_info->colnum) {
+ case COLUMN_ME5FILEINDEX:
+ snmp_set_var_typed_value(var, ASN_UNSIGNED,
+ (u_char *) & data->findex,
+ sizeof(data->findex));
+ break;
+
+ case COLUMN_ME5FILENAME:
+ snmp_set_var_typed_value(var, ASN_OCTET_STR,
+ (u_char *) data->fileName,
+ strlen(data->fileName));
+ break;
+
+ case COLUMN_ME5FILESIZE:
+ snmp_set_var_typed_value(var, ASN_UNSIGNED,
+ (u_char *) & data->fileSize,
+ sizeof(data->fileSize));
+ break;
+
+ case COLUMN_ME5FILEPERM:
+ snmp_set_var_typed_value(var, ASN_OCTET_STR, (u_char *) data->filePerm,
+ strlen(data->filePerm));
+ break;
+
+ default:
+ /* We shouldn't get here */
+ snmp_log(LOG_ERR,
+ "problem encountered in me5FileTable_handler: unknown column\n");
+ }
+ break;
+
+ case MODE_SET_RESERVE1:
+ /* set handling... */
+ switch (table_info->colnum) {
+ /*
+ * Check that the value being set is acceptable
+ */
+ case COLUMN_ME5FILENAME:
+ if (var->type != ASN_OCTET_STR) {
+ DEBUGMSGTL(("me5FileTable", "COLUMN NAME\n"));
+ DEBUGMSGTL(("me5FileTable", "%x not octet string type", var->type));
+ netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE);
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (!var->val.string) {
+ DEBUGMSGTL(("me2FileTable", "Empty file name"));
+ netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE);
+ return SNMP_ERR_WRONGVALUE;
+ }
+ break;
+ default:
+ /* We shouldn't get here */
+ snmp_log(LOG_ERR,
+ "problem encountered in me5FileTable_handler: unknown column\n");
+ netsnmp_set_request_error(reqinfo, request, SNMP_ERR_READONLY);
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ break;
+ case MODE_SET_RESERVE2:
+ /*
+ * This is conventially where any necesary resources are
+ * allocated (e.g. calls to malloc)
+ */
+
+ /* Store old info for undo later */
+
+ undofn = GetFileName(data->findex);
+ if (undofn) {
+ if (!(fileName = strdup(undofn))) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_RESOURCEUNAVAILABLE);
+ } else
+ netsnmp_request_add_list_data(request,
+ netsnmp_create_data_list
+ (ME5FILE_SET_FILENAME, fileName,
+ free));
+
+ }
+ break;
+ case MODE_SET_FREE:
+
+ /*
+ * This is where any of the above resources are freed again
+ * (because one of the other values being SET failed for some
+ * reason).
+ */
+
+ /*
+ * The netsnmp_free_list_data should take care of the alocated
+ * resources
+ */
+
+ break;
+ case MODE_SET_ACTION:
+ /*
+ * Set the variable as requested. Note that this may need to be
+ * reversed, so save any information needed to do this.
+ */
+ len = var->val_len;
+ var->val.string[len] = '\0';
+ if (!ChangeItem(data->findex, (char *) var->val.string )) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_COMMITFAILED);
+ }
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * Everything worked, so we can discard any saved information,
+ * and make the change permanent (e.g. write to the config file).
+ * We also free any allocated resources.
+ *
+ */
+
+ /* Persist the file information */
+
+ snprintf(&filebuf[0], MAXNAMELEN, "demo5_file%d %s",
+ data->findex, data->fileName);
+
+
+
+ read_config_store(DEMO5_CONF_FILE, &filebuf[0]);
+
+ /*
+ * The netsnmp_free_list_data should take care of the alocated
+ * resources
+ */
+
+
+ break;
+ case MODE_SET_UNDO:
+ /*
+ * Something failed, so re-set the variable to its previous value
+ * (and free any allocated resources).
+ */
+
+ if (GetFileName(data->findex)) {
+ /******* Get the saved value ************/
+ undofn = (char *) netsnmp_request_get_list_data(request,
+ ME5FILE_SET_FILENAME);
+ if (!ChangeItem(data->findex, undofn)) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_UNDOFAILED);
+ }
+ }
+ break;
+
+ default:
+ snmp_log(LOG_ERR,
+ "problem encountered in me5FileTable_handler: unsupported mode\n");
+ }
+ }
+
+ return SNMP_ERR_NOERROR;
+}
+
+/* Function to add a fileName to the linked list of files */
+
+int
+AddItem(char *fileName)
+{
+
+ fileEntry *fprt = fileList;
+ struct stat fAttrib; /* Need to check if memory is valid */
+ if (!fileName || !strlen(fileName)) {
+ return FALSE;
+ }
+ if (stat(fileName, &fAttrib) == -1) {
+ /*
+ * Unable to get the file information, it could be more than file not
+ * exists if (errno == ENOENT) { return FALSE; } return FALSE;
+ */
+ DEBUGMSGTL(("demo_module_5", "Can't access the file %s", fileName));
+ }
+ if (fprt != NULL) {
+ while (fprt->next != NULL) {
+ fprt = fprt->next;
+ }
+ fprt->next = (fileEntry *) malloc(sizeof(fileEntry));
+ fprt->next->findex = fprt->findex + 1;
+ fprt = fprt->next;
+ fprt->next = NULL;
+ strcpy(fprt->fileName, fileName);
+ fprt->fileSize = fAttrib.st_size;
+ sprintf(fprt->filePerm, "%d", fAttrib.st_mode);
+ } else {
+ fprt = (fileEntry *) malloc(sizeof(fileEntry));
+ fprt->next = NULL;
+ fprt->findex = 1;
+ strcpy(fprt->fileName, fileName);
+ fprt->fileSize = fAttrib.st_size;
+ sprintf(fprt->filePerm, "%d", fAttrib.st_mode);
+ fileList = fprt;
+ }
+
+ return TRUE;
+}
+
+/*
+ * Function to change the file for a particular index. This function is
+ * called when a snmp set request arrives to change the list of files being
+ * monitored.
+ */
+
+int
+ChangeItem(int fileIndex, char *fileName)
+{
+
+ fileEntry *tempp = fileList;
+
+ if (!fileName || !strlen(fileName)) {
+ return FALSE;
+ }
+
+ while (tempp != NULL) {
+ if (tempp->findex == fileIndex) {
+ strcpy(tempp->fileName, fileName);
+ switch(fileIndex) {
+ case 1:
+ strcpy(file1, fileName);
+ case 2:
+ strcpy(file2, fileName);
+ case 3:
+ strcpy(file3, fileName);
+ case 4:
+ strcpy(file4, fileName);
+ }
+ return TRUE;
+
+ }
+ tempp = tempp->next;
+ }
+
+ return FALSE;
+}
+
+/* Function to return the filename corresponding to an index */
+
+char *
+GetFileName(int fIndex)
+{
+ fileEntry *fprt = fileList;
+ while (fprt != NULL) {
+ if (fprt->findex == fIndex) {
+ return fprt->fileName;
+ }
+ fprt = fprt->next;
+ }
+ return NULL;
+
+}
+
+/*
+ * Function that is called whenever interested tokens are encountered in
+ * demo_module_5.conf file. The token values represent the persistent filename
+ * information.
+ */
+
+void
+demo5_load_tokens(const char *token, char *cptr)
+{
+
+ if (strcmp(token, "demo5_file1") == 0) {
+ strcpy(file1, cptr);
+ } else if (strcmp(token, "demo5_file2") == 0) {
+ strcpy(file2, cptr);
+ } else if (strcmp(token, "demo5_file3") == 0) {
+ strcpy(file3, cptr);
+ } else if (strcmp(token, "demo5_file4") == 0) {
+ strcpy(file4, cptr);
+ } else {
+ /* Do Nothing */
+ }
+
+ return;
+
+}
+
+/*
+ * Function that persists file information. This is called by the agent
+ * whenever data needs to be persisted.
+ */
+
+int
+demo5_persist_data(int a, int b, void *c, void *d)
+{
+
+ char filebuf[300];
+
+
+ sprintf(filebuf, "demo5_file1 %s", file1);
+ read_config_store(DEMO5_CONF_FILE, filebuf);
+
+
+ sprintf(filebuf, "demo5_file2 %s", file2);
+ read_config_store(DEMO5_CONF_FILE, filebuf);
+
+
+ sprintf(filebuf, "demo5_file3 %s", file3);
+ read_config_store(DEMO5_CONF_FILE, filebuf);
+
+
+ sprintf(filebuf, "demo5_file4 %s", file4);
+ read_config_store(DEMO5_CONF_FILE, filebuf);
+
+}
+
+/*
+ * Callback function that is called after all the configuration files are
+ * read by the agent. See init_demo_module_5 function to see how this
+ * callback is specified.
+ *
+ * When this function is called, any persistent file information would have been
+ * read into the module. These files are added to the file list.
+ *
+ * The callback function to persist data (demo5_persist_data) is registered.
+ */
+
+int
+demo5_post_read_config(int a, int b, void *c, void *d)
+{
+
+ if (!AddItem(file1))
+ snmp_log(LOG_ERR, "Failed to add instance in init_demo_module_5\n");
+ if (!AddItem(file2))
+ snmp_log(LOG_ERR, "Failed to add instance in init_demo_module_5\n");
+ if (!AddItem(file3))
+ snmp_log(LOG_ERR, "Failed to add instance in init_demo_module_5\n");
+ if (!AddItem(file4))
+ snmp_log(LOG_ERR, "Failed to add instance in init_demo_module_5\n");
+
+
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ demo5_persist_data, NULL);
+
+
+}
+