📄 example.c
字号:
/* * Template MIB group implementation - example.c * *//* include important headers */#include <config.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif/* needed by util_funcs.h */#if TIME_WITH_SYS_TIME# ifdef WIN32# include <sys/timeb.h># else# include <sys/time.h># endif# include <time.h>#else# if HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#if HAVE_WINSOCK_H#include <winsock.h>#endif#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif/* mibincl.h contains all the snmp specific headers to define the return types and various defines and structures. */#include "mibincl.h"/* header_generic() comes from here */#include "util_funcs.h"#include "agent_read_config.h"/* include our .h file */#include "example.h" /* * Certain objects can be set via configuration file directives. * These variables hold the values for such objects, as they need to * be accessible to both the config handlers, and the callback routine. */#define EXAMPLE_STR_LEN 300#define EXAMPLE_STR_DEFAULT "life the universe and everything"int example_int = 42;char example_str[ EXAMPLE_STR_LEN ]; /* Forward declarations for the config handlers */void example_parse_config_exampleint( const char *token, char *cptr );void example_parse_config_examplestr( const char *token, char *cptr );void example_free_config_exampleint( void );void example_free_config_examplestr( void ); /********************* * * Initialisation & common implementation functions * *********************/ /* * This array structure defines a representation of the * MIB being implemented. * * The type of the array is 'struct variableN', where N is * large enough to contain the longest OID sub-component * being loaded. This will normally be the maximum value * of the fifth field in each line. In this case, the second * and third entries are both of size 2, so we're using * 'struct variable2' * * The supported values for N are listed in <agent/var_struct.h> * If the value you need is not listed there, simply use the * next largest that is. * * The format of each line is as follows * (using the first entry as an example): * 1: EXAMPLESTRING: * The magic number defined in the example header file. * This is passed to the callback routine and is used * to determine which object is being queried. * 2: ASN_OCTET_STR: * The type of the object. * Valid types are listed in <snmp_impl.h> * 3: RONLY (or RWRITE): * Whether this object can be SET or not. * 4: var_example: * The callback routine, used when the object is queried. * This will usually be the same for all objects in a module * and is typically defined later in this file. * 5: 1: * The length of the OID sub-component (the next field) * 6: {1}: * The OID sub-components of this entry. * In other words, the bits of the full OID that differ * between the various entries of this array. * This value is appended to the common prefix (defined later) * to obtain the full OID of each entry. */struct variable2 example_variables[] = { { EXAMPLESTRING, ASN_OCTET_STR, RONLY, var_example, 1, {1}}, { EXAMPLEINTEGER, ASN_INTEGER, RWRITE, var_example, 2, {2,1}}, { EXAMPLEOBJECTID, ASN_OBJECT_ID, RONLY, var_example, 2, {2,2}}, { EXAMPLETIMETICKS, ASN_TIMETICKS, RONLY, var_example, 1, {3}}, { EXAMPLEIPADDRESS, ASN_IPADDRESS, RONLY, var_example, 1, {4}}, { EXAMPLECOUNTER, ASN_COUNTER, RONLY, var_example, 1, {5}}, { EXAMPLEGAUGE, ASN_GAUGE, RONLY, var_example, 1, {6}}, { EXAMPLETRIGGERTRAP, ASN_INTEGER, RWRITE, var_example, 1, {7}}, { EXAMPLETRIGGERTRAP2, ASN_INTEGER, RWRITE, var_example, 1, {8}} }; /* * This array defines the OID of the top of the mib tree that we're * registering underneath. * Note that this needs to be the correct size for the OID being * registered, so that the length of the OID can be calculated. * The format given here is the simplest way to achieve this. */ oid example_variables_oid[] = { 1,3,6,1,4,1,2021,254 }; /* * This function is called at the time the agent starts up * to do any initializations that might be required. * * In theory it is optional and can be omitted if no * initialization is needed. In practise, every module * will need to register itself (or the objects being * implemented will not appear in the MIB tree), and this * registration is typically done here. * * If this function is added or removed, you must re-run * the configure script, to detect this change. */void init_example(void){ /* * Register ourselves with the agent to handle our mib tree. * The arguments are: * descr: A short description of the mib group being loaded. * var: The variable structure to load. * (the name of the variable structure defined above) * vartype: The type of this variable structure * theoid: The OID pointer this MIB is being registered underneath. */ REGISTER_MIB("example", example_variables, variable2, example_variables_oid); /* * Register config handlers for the two objects that can be set * via configuration file directive. * Also set a default value for the string object. Note that the * example integer variable was initialised above. */ strcpy( example_str, EXAMPLE_STR_DEFAULT ); snmpd_register_config_handler( "exampleint", example_parse_config_exampleint, example_free_config_exampleint, "exampleint value" ); snmpd_register_config_handler( "examplestr", example_parse_config_examplestr, example_free_config_examplestr, "examplestr value" ); snmpd_register_config_handler( "examplestring", example_parse_config_examplestr, example_free_config_examplestr, "examplestring value" ); /* * One common requirement is to read values from the kernel. * This is usually initialised here, to speed up access when the * information is read in, as a response to an incoming request. * * This module doesn't actually use this mechanism, * so this call is commented out here. */ /* auto_nlist( "example_symbol", 0, 0 ); */} /********************* * * Configuration file handling functions * *********************/voidexample_parse_config_exampleint( const char *token, char *cptr ){ example_int = atoi( cptr );}voidexample_parse_config_examplestr( const char *token, char *cptr ){ /* * Make sure the string fits in the space allocated for it. */ if ( strlen( cptr ) < EXAMPLE_STR_LEN ) strcpy( example_str, cptr ); else { /* * Truncate the string if necessary. * An alternative approach would be to log an error, * and discard this value altogether. */ strncpy( example_str, cptr, EXAMPLE_STR_LEN-3 ); example_str[ EXAMPLE_STR_LEN-3 ] = 0; strcat( example_str, "..." ); }} /* We don't need to do anything special when closing down */voidexample_free_config_exampleint( void ) {}voidexample_free_config_examplestr( void ) {} /********************* * * System specific implementation functions * *********************/ /* * Define the callback function used in the example_variables structure. * This is called whenever an incoming request refers to an object * within this sub-tree. * * Four of the parameters are used to pass information in. * These are: * vp The entry from the 'example_variables' array for the * object being queried. * name The OID from the request. * length The length of this OID. * exact A flag to indicate whether this is an 'exact' request * (GET/SET) or an 'inexact' one (GETNEXT/GETBULK). * * Four of the parameters are used to pass information back out. * These are: * name The OID being returned. * length The length of this OID. * var_len The length of the answer being returned. * write_method A pointer to the SET function for this object. * * Note that name & length serve a dual purpose in both roles. */u_char *var_example(struct variable *vp, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method){ /* * The result returned from this function needs to be a pointer to * static data (so that it can be accessed from outside). * Define suitable variables for any type of data we may return. */ static char string[EXAMPLE_STR_LEN]; /* for EXAMPLESTRING */ static oid oid_ret[8]; /* for EXAMPLEOBJECTID */ static long long_ret; /* for everything else */ /* * Before returning an answer, we need to check that the request * refers to a valid instance of this object. The utility routine * 'header_generic' can be used to do this for scalar objects. * * This routine 'header_simple_table' does the same thing for "simple" * tables. (See the AGENT.txt file for the definition of a simple table). * * Both these utility routines also set up default values for the * return arguments (assuming the check succeeded). * The name and length are set suitably for the current object, * var_len assumes that the result is an integer of some form, * and write_method assumes that the object cannot be set. * * If these assumptions are correct, this callback routine simply * needs to return a pointer to the appropriate value (using 'long_ret'). * Otherwise, 'var_len' and/or 'write_method' should be set suitably. */ DEBUGMSGTL(("example","var_example entered\n")); if (header_generic(vp, name, length, exact, var_len, write_method) == MATCH_FAILED) return NULL; /* * Many object will need to obtain data from the operating system in * order to return the appropriate value. Typically, this is done * here - immediately following the 'header' call, and before the * switch statement. This is particularly appropriate if a single * interface call can return data for all the objects supported. * * This example module does not rely on external data, so no such * calls are needed in this case. */ /* * Now use the magic number from the variable pointer 'vp' to * select the particular object being queried. * In each case, one of the static objects is set up with the * appropriate information, and returned mapped to a 'u_char *' */ switch (vp->magic){ case EXAMPLESTRING: sprintf(string, example_str); /* * Note that the assumption that the answer will be an * integer does not hold true in this case, so the length * of the answer needs to be set explicitly. */ *var_len = strlen(string); return (u_char *) string; case EXAMPLEINTEGER: /* * Here the length assumption is correct, but the * object is writeable, so we need to set the * write_method pointer as well as the current value. */ long_ret = example_int; *write_method = write_exampleint; return (u_char *) &long_ret; case EXAMPLEOBJECTID: oid_ret[0] = 1; oid_ret[1] = 3; oid_ret[2] = 6; oid_ret[3] = 1; oid_ret[4] = 4; oid_ret[5] = oid_ret[6] = oid_ret[7] = 42; /* * Again, the assumption regarding the answer length is wrong. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -