k***@air.co.jp
2003-05-08 03:02:07 UTC
Hello.
I implemented my original C code at ~net-snmp-5.0.8/agent/mibgroup .
The snmpwalk command works well.
---
[***@sydney mibgroup]$ snmpwalk -c public localhost air
MY-MIB::hostPing.0 = ""
MY-MIB::hostIP.0 = ""
---
But snmpget/snmpset command isn't work well.
---
[***@sydney mibgroup]$ snmpget -c public localhost hostPing
Error in packet
Reason: (noSuchName) There is no such variable name in this MIB.
Failed object: MY-MIB::hostPing
[***@sydney mibgroup]$ snmpset -c public localhost hostPing s "/bin/ping"
Error in packet.
Reason: (noSuchName) There is no such variable name in this MIB.
---
Why doesn't SET/GET function work well?
Perhaps I think that register operation(function) is needed in which
point.
But I don't know the point.
Please tell me.
My souce code is as follows;
---
/*
* Template MIB group implementation - mymib.c
*
*/
/*
* include important headers
*/
#include <net-snmp/net-snmp-config.h>
#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
/*
* needed by util_funcs.h
*/
# include <sys/time.h>
#include <netinet/in.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
/*
* header_generic() comes from here
*/
#include "util_funcs.h"
/*
* include our .h file
*/
#include "mymib.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 MYMIB_STR_LEN 300
#define MYMIB_STR_DEFAULT "life the universe and everything"
int mymib_int = 42;
char mymib_str[MYMIB_STR_LEN];
/*
* Forward declarations for the config handlers
*/
void mymib_parse_config_mymibint(const char *token,
char *cptr);
void mymib_parse_config_mymibstr(const char *token,
char *cptr);
void mymib_free_config_mymibint(void);
void mymib_free_config_mymibstr(void);
int write_mymibstr(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len);
u_char * get_mymibstr(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len);
/*********************
*
* 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 mymib):
* 1: MYMIBSTRING:
* The magic number defined in the mymib 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_mymib:
* 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 mymib_variables[] = {
{hostPing, ASN_OCTET_STR, RWRITE, var_mymib, 1, {1}},
{hostIP, ASN_OCTET_STR, RWRITE, var_mymib, 1, {2}},
/*
{MYMIBSTRING, ASN_OCTET_STR, RONLY, var_mymib, 1, {1}},
{MYMIBINTEGER, ASN_INTEGER, RWRITE, var_mymib, 2, {2, 1}},
{MYMIBOBJECTID, ASN_OBJECT_ID, RONLY, var_mymib, 2, {2, 2}},
{MYMIBTIMETICKS, ASN_TIMETICKS, RONLY, var_mymib, 1, {3}},
{MYMIBIPADDRESS, ASN_IPADDRESS, RONLY, var_mymib, 1, {4}},
{MYMIBCOUNTER, ASN_COUNTER, RONLY, var_mymib, 1, {5}},
{MYMIBGAUGE, ASN_GAUGE, RONLY, var_mymib, 1, {6}},
{MYMIBTRIGGERTRAP, ASN_INTEGER, RWRITE, var_mymib, 1, {7}},
{MYMIBTRIGGERTRAP2, ASN_INTEGER, RWRITE, var_mymib, 1, {8}}
*/
};
char mymib_mon[10][256];
/*
* 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 mymib_variables_oid[] = { 1, 3, 6, 1, 4, 1, 14886, 1, 1 };
/*
* 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_mymib(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("mymib", mymib_variables, variable2,
mymib_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
* mymib integer variable was initialised above.
*/
strncpy(mymib_str, MYMIB_STR_DEFAULT, MYMIB_STR_LEN);
/*
snmpd_register_config_handler("mymibint",
mymib_parse_config_mymibint,
mymib_free_config_mymibint,
"mymibint value");
snmpd_register_config_handler("mymibstr",
mymib_parse_config_mymibstr,
mymib_free_config_mymibstr,
"mymibstr value");
snmpd_register_config_handler("mymibstring",
mymib_parse_config_mymibstr,
mymib_free_config_mymibstr,
"mymibstring value");
*/
snmpd_register_config_handler("mymibstr",
write_mymibstr,
get_mymibstr,
"mymibstr value");
snmpd_register_config_handler("mymibstring",
mymib_parse_config_mymibstr,
mymib_free_config_mymibstr,
"mymibstring 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( "mymib_symbol", 0, 0 );
*/
}
/*********************
*
* Configuration file handling functions
*
*********************/
void
mymib_parse_config_mymibint(const char *token, char *cptr)
{
mymib_int = atoi(cptr);
}
void
mymib_parse_config_mymibstr(const char *token, char *cptr)
{
fprintf(stderr,"write_mymibstr\n");fflush(stderr);
/*
* Make sure the string fits in the space allocated for it.
*/
if (strlen(cptr) < MYMIB_STR_LEN)
strcpy(mymib_str, cptr);
else {
/*
* Truncate the string if necessary.
* An alternative approach would be to log an error,
* and discard this value altogether.
*/
strncpy(mymib_str, cptr, MYMIB_STR_LEN - 4);
mymib_str[MYMIB_STR_LEN - 4] = 0;
strcat(mymib_str, "...");
mymib_str[MYMIB_STR_LEN - 1] = 0;
}
}
/*
* We don't need to do anything special when closing down
*/
void
mymib_free_config_mymibint(void)
{
}
void
mymib_free_config_mymibstr(void)
{
}
/*********************
*
* System specific implementation functions
*
*********************/
/*
* Define the callback function used in the mymib_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 'mymib_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_mymib(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[MYMIB_STR_LEN]; /* for MYMIBSTRING */
static oid oid_ret[8]; /* for MYMIBOBJECTID */
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(("mymib", "var_mymib 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 mymib 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 hostPing:
*write_method = write_mymibstr;
sprintf(string, mymib_mon[0]);
/*
* 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 hostIP:
*write_method = write_mymibstr;
sprintf(string, mymib_mon[1]);
/*
* 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;
default:
/*
* This will only be triggered if there's a problem with
* the coding of the module. SNMP requests that reference
* a non-existant OID will be directed elsewhere.
* If this branch is reached, log an error, so that
* the problem can be investigated.
*/
DEBUGMSGTL(("snmpd", "unknown sub-id %d in mymibs/var_mymib\n",
vp->magic));
}
/*
* If we fall through to here, fail by returning NULL.
* This is essentially a continuation of the 'default' case above.
*/
return NULL;
}
/*********************
*
* Writeable object SET handling routines
*
*********************/
int
write_mymibstr(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len)
{
/*
* Define an arbitrary maximum permissible value
*/
#define MAX_MYMIB_INT 100
static long intval;
static long old_intval;
fprintf(stderr,"write_mymibstr\n");fflush(stderr);
switch (action) {
/*
case SET:
break;
case SET_RESERVE1:
break;
*/
case RESERVE1:
break;
default:
break;
}
}
u_char * get_mymibstr(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len)
{
switch (action) {
case MODE_GET:
case MODE_GETNEXT:
break;
case RESERVE1:
break;
default:
break;
}
}
int
write_mymibint(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len)
{
/*
* Define an arbitrary maximum permissible value
*/
#define MAX_MYMIB_INT 100
static long intval;
static long old_intval;
switch (action) {
case RESERVE1:
/*
* Check that the value being set is acceptable
*/
if (var_val_type != ASN_INTEGER) {
DEBUGMSGTL(("mymib", "%x not integer type", var_val_type));
return SNMP_ERR_WRONGTYPE;
}
if (var_val_len > sizeof(long)) {
DEBUGMSGTL(("mymib", "wrong length %x", var_val_len));
return SNMP_ERR_WRONGLENGTH;
}
intval = *((long *) var_val);
if (intval > MAX_MYMIB_INT) {
DEBUGMSGTL(("mymib", "wrong value %x", intval));
return SNMP_ERR_WRONGVALUE;
}
/*
*/
break;
case RESERVE2:
/*
* This is conventially where any necesary
* resources are allocated (e.g. calls to malloc)
* Here, we are using static variables
* so don't need to worry about this.
*/
break;
case FREE:
/*
* This is where any of the above resources
* are freed again (because one of the other
* values being SET failed for some reason).
* Again, since we are using static variables
* we don't need to worry about this either.
*/
break;
case ACTION:
/*
* Set the variable as requested.
* Note that this may need to be reversed,
* so save any information needed to do this.
*/
old_intval = mymib_int;
mymib_int = intval;
break;
case UNDO:
/*
* Something failed, so re-set the
* variable to its previous value
* (and free any allocated resources).
*/
mymib_int = old_intval;
break;
case 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.
*
* In this case, there's nothing to do.
*/
break;
}
return SNMP_ERR_NOERROR;
}
int
write_mymibtrap(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len)
{
long intval;
DEBUGMSGTL(("mymib", "write_mymibtrap entered: action=%d\n",
action));
switch (action) {
case RESERVE1:
/*
* The only acceptable value is the integer 1
*/
if (var_val_type != ASN_INTEGER) {
DEBUGMSGTL(("mymib", "%x not integer type", var_val_type));
return SNMP_ERR_WRONGTYPE;
}
if (var_val_len > sizeof(long)) {
DEBUGMSGTL(("mymib", "wrong length %x", var_val_len));
return SNMP_ERR_WRONGLENGTH;
}
intval = *((long *) var_val);
if (intval != 1) {
DEBUGMSGTL(("mymib", "wrong value %x", intval));
return SNMP_ERR_WRONGVALUE;
}
break;
case RESERVE2:
/*
* No resources are required....
*/
break;
case FREE:
/*
* ... so no resources need be freed
*/
break;
case ACTION:
/*
* Having triggered the sending of a trap,
* it would be impossible to revoke this,
* so we can't actually invoke the action here.
*/
break;
case UNDO:
/*
* We haven't done anything yet,
* so there's nothing to undo
*/
break;
case COMMIT:
/*
* Everything else worked, so it's now safe
* to trigger the trap.
* Note that this is *only* acceptable since
* the trap sending routines are "failsafe".
* (In fact, they can fail, but they return no
* indication of this, which is the next best thing!)
*/
DEBUGMSGTL(("mymib", "write_mymibtrap sending the trap\n",
action));
send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 99);
DEBUGMSGTL(("mymib", "write_mymibtrap trap sent\n", action));
break;
}
return SNMP_ERR_NOERROR;
}
/*
* this documents how to send a SNMPv2 (and higher) trap via the
* send_v2trap() API.
*
* Coding SNMP-v2 Trap:
*
* The SNMPv2-Trap PDU contains at least a pair of object names and
* values: - sysUpTime.0 whose value is the time in hundredths of a
* second since the netwok management portion of system was last
* reinitialized. - snmpTrapOID.0 which is part of the trap group SNMPv2
* MIB whose value is the object-id of the specific trap you have defined
* in your own MIB. Other variables can be added to caracterize the
* trap.
*
* The function send_v2trap adds automaticallys the two objects but the
* value of snmpTrapOID.0 is 0.0 by default. If you want to add your trap
* name, you have to reconstruct this object and to add your own
* variable.
*
*/
int
write_mymibtrap2(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len)
{
long intval;
/*
* these variales will be used when we send the trap
*/
oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; /* snmpTrapOID.0 */
oid demo_trap[] = { 1, 3, 6, 1, 4, 1, 2021, 13, 990 }; /*demo-trap */
oid mymib_string_oid[] =
{ 1, 3, 6, 1, 4, 1, 2021, 254, 1, 0 };
static netsnmp_variable_list var_trap;
static netsnmp_variable_list var_obj;
DEBUGMSGTL(("mymib", "write_mymibtrap2 entered: action=%d\n",
action));
switch (action) {
case RESERVE1:
/*
* The only acceptable value is the integer 1
*/
if (var_val_type != ASN_INTEGER) {
DEBUGMSGTL(("mymib", "%x not integer type", var_val_type));
return SNMP_ERR_WRONGTYPE;
}
if (var_val_len > sizeof(long)) {
DEBUGMSGTL(("mymib", "wrong length %x", var_val_len));
return SNMP_ERR_WRONGLENGTH;
}
intval = *((long *) var_val);
if (intval != 1) {
DEBUGMSGTL(("mymib", "wrong value %x", intval));
return SNMP_ERR_WRONGVALUE;
}
break;
case RESERVE2:
/*
* No resources are required....
*/
break;
case FREE:
/*
* ... so no resources need be freed
*/
break;
case ACTION:
/*
* Having triggered the sending of a trap,
* it would be impossible to revoke this,
* so we can't actually invoke the action here.
*/
break;
case UNDO:
/*
* We haven't done anything yet,
* so there's nothing to undo
*/
break;
case COMMIT:
/*
* Everything else worked, so it's now safe
* to trigger the trap.
* Note that this is *only* acceptable since
* the trap sending routines are "failsafe".
* (In fact, they can fail, but they return no
* indication of this, which is the next best thing!)
*/
/*
* trap definition objects
*/
var_trap.next_variable = &var_obj; /* next variable */
var_trap.name = objid_snmptrap; /* snmpTrapOID.0 */
var_trap.name_length = sizeof(objid_snmptrap) / sizeof(oid); /* number of sub-ids */
var_trap.type = ASN_OBJECT_ID;
var_trap.val.objid = demo_trap; /* demo-trap objid */
var_trap.val_len = sizeof(demo_trap); /* length in bytes (not number of subids!) */
/*
* additional objects
*/
var_obj.next_variable = NULL; /* No more variables after this one */
var_obj.name = mymib_string_oid;
var_obj.name_length = sizeof(mymib_string_oid) / sizeof(oid); /* number of sub-ids */
var_obj.type = ASN_OCTET_STR; /* type of variable */
var_obj.val.string = mymib_str; /* value */
var_obj.val_len = strlen(mymib_str);
DEBUGMSGTL(("mymib", "write_mymibtrap2 sending the v2 trap\n",
action));
send_v2trap(&var_trap);
DEBUGMSGTL(("mymib", "write_mymibtrap2 v2 trap sent\n",
action));
break;
}
return SNMP_ERR_NOERROR;
}
---
I implemented my original C code at ~net-snmp-5.0.8/agent/mibgroup .
The snmpwalk command works well.
---
[***@sydney mibgroup]$ snmpwalk -c public localhost air
MY-MIB::hostPing.0 = ""
MY-MIB::hostIP.0 = ""
---
But snmpget/snmpset command isn't work well.
---
[***@sydney mibgroup]$ snmpget -c public localhost hostPing
Error in packet
Reason: (noSuchName) There is no such variable name in this MIB.
Failed object: MY-MIB::hostPing
[***@sydney mibgroup]$ snmpset -c public localhost hostPing s "/bin/ping"
Error in packet.
Reason: (noSuchName) There is no such variable name in this MIB.
---
Why doesn't SET/GET function work well?
Perhaps I think that register operation(function) is needed in which
point.
But I don't know the point.
Please tell me.
My souce code is as follows;
---
/*
* Template MIB group implementation - mymib.c
*
*/
/*
* include important headers
*/
#include <net-snmp/net-snmp-config.h>
#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
/*
* needed by util_funcs.h
*/
# include <sys/time.h>
#include <netinet/in.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
/*
* header_generic() comes from here
*/
#include "util_funcs.h"
/*
* include our .h file
*/
#include "mymib.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 MYMIB_STR_LEN 300
#define MYMIB_STR_DEFAULT "life the universe and everything"
int mymib_int = 42;
char mymib_str[MYMIB_STR_LEN];
/*
* Forward declarations for the config handlers
*/
void mymib_parse_config_mymibint(const char *token,
char *cptr);
void mymib_parse_config_mymibstr(const char *token,
char *cptr);
void mymib_free_config_mymibint(void);
void mymib_free_config_mymibstr(void);
int write_mymibstr(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len);
u_char * get_mymibstr(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len);
/*********************
*
* 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 mymib):
* 1: MYMIBSTRING:
* The magic number defined in the mymib 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_mymib:
* 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 mymib_variables[] = {
{hostPing, ASN_OCTET_STR, RWRITE, var_mymib, 1, {1}},
{hostIP, ASN_OCTET_STR, RWRITE, var_mymib, 1, {2}},
/*
{MYMIBSTRING, ASN_OCTET_STR, RONLY, var_mymib, 1, {1}},
{MYMIBINTEGER, ASN_INTEGER, RWRITE, var_mymib, 2, {2, 1}},
{MYMIBOBJECTID, ASN_OBJECT_ID, RONLY, var_mymib, 2, {2, 2}},
{MYMIBTIMETICKS, ASN_TIMETICKS, RONLY, var_mymib, 1, {3}},
{MYMIBIPADDRESS, ASN_IPADDRESS, RONLY, var_mymib, 1, {4}},
{MYMIBCOUNTER, ASN_COUNTER, RONLY, var_mymib, 1, {5}},
{MYMIBGAUGE, ASN_GAUGE, RONLY, var_mymib, 1, {6}},
{MYMIBTRIGGERTRAP, ASN_INTEGER, RWRITE, var_mymib, 1, {7}},
{MYMIBTRIGGERTRAP2, ASN_INTEGER, RWRITE, var_mymib, 1, {8}}
*/
};
char mymib_mon[10][256];
/*
* 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 mymib_variables_oid[] = { 1, 3, 6, 1, 4, 1, 14886, 1, 1 };
/*
* 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_mymib(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("mymib", mymib_variables, variable2,
mymib_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
* mymib integer variable was initialised above.
*/
strncpy(mymib_str, MYMIB_STR_DEFAULT, MYMIB_STR_LEN);
/*
snmpd_register_config_handler("mymibint",
mymib_parse_config_mymibint,
mymib_free_config_mymibint,
"mymibint value");
snmpd_register_config_handler("mymibstr",
mymib_parse_config_mymibstr,
mymib_free_config_mymibstr,
"mymibstr value");
snmpd_register_config_handler("mymibstring",
mymib_parse_config_mymibstr,
mymib_free_config_mymibstr,
"mymibstring value");
*/
snmpd_register_config_handler("mymibstr",
write_mymibstr,
get_mymibstr,
"mymibstr value");
snmpd_register_config_handler("mymibstring",
mymib_parse_config_mymibstr,
mymib_free_config_mymibstr,
"mymibstring 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( "mymib_symbol", 0, 0 );
*/
}
/*********************
*
* Configuration file handling functions
*
*********************/
void
mymib_parse_config_mymibint(const char *token, char *cptr)
{
mymib_int = atoi(cptr);
}
void
mymib_parse_config_mymibstr(const char *token, char *cptr)
{
fprintf(stderr,"write_mymibstr\n");fflush(stderr);
/*
* Make sure the string fits in the space allocated for it.
*/
if (strlen(cptr) < MYMIB_STR_LEN)
strcpy(mymib_str, cptr);
else {
/*
* Truncate the string if necessary.
* An alternative approach would be to log an error,
* and discard this value altogether.
*/
strncpy(mymib_str, cptr, MYMIB_STR_LEN - 4);
mymib_str[MYMIB_STR_LEN - 4] = 0;
strcat(mymib_str, "...");
mymib_str[MYMIB_STR_LEN - 1] = 0;
}
}
/*
* We don't need to do anything special when closing down
*/
void
mymib_free_config_mymibint(void)
{
}
void
mymib_free_config_mymibstr(void)
{
}
/*********************
*
* System specific implementation functions
*
*********************/
/*
* Define the callback function used in the mymib_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 'mymib_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_mymib(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[MYMIB_STR_LEN]; /* for MYMIBSTRING */
static oid oid_ret[8]; /* for MYMIBOBJECTID */
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(("mymib", "var_mymib 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 mymib 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 hostPing:
*write_method = write_mymibstr;
sprintf(string, mymib_mon[0]);
/*
* 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 hostIP:
*write_method = write_mymibstr;
sprintf(string, mymib_mon[1]);
/*
* 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;
default:
/*
* This will only be triggered if there's a problem with
* the coding of the module. SNMP requests that reference
* a non-existant OID will be directed elsewhere.
* If this branch is reached, log an error, so that
* the problem can be investigated.
*/
DEBUGMSGTL(("snmpd", "unknown sub-id %d in mymibs/var_mymib\n",
vp->magic));
}
/*
* If we fall through to here, fail by returning NULL.
* This is essentially a continuation of the 'default' case above.
*/
return NULL;
}
/*********************
*
* Writeable object SET handling routines
*
*********************/
int
write_mymibstr(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len)
{
/*
* Define an arbitrary maximum permissible value
*/
#define MAX_MYMIB_INT 100
static long intval;
static long old_intval;
fprintf(stderr,"write_mymibstr\n");fflush(stderr);
switch (action) {
/*
case SET:
break;
case SET_RESERVE1:
break;
*/
case RESERVE1:
break;
default:
break;
}
}
u_char * get_mymibstr(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len)
{
switch (action) {
case MODE_GET:
case MODE_GETNEXT:
break;
case RESERVE1:
break;
default:
break;
}
}
int
write_mymibint(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len)
{
/*
* Define an arbitrary maximum permissible value
*/
#define MAX_MYMIB_INT 100
static long intval;
static long old_intval;
switch (action) {
case RESERVE1:
/*
* Check that the value being set is acceptable
*/
if (var_val_type != ASN_INTEGER) {
DEBUGMSGTL(("mymib", "%x not integer type", var_val_type));
return SNMP_ERR_WRONGTYPE;
}
if (var_val_len > sizeof(long)) {
DEBUGMSGTL(("mymib", "wrong length %x", var_val_len));
return SNMP_ERR_WRONGLENGTH;
}
intval = *((long *) var_val);
if (intval > MAX_MYMIB_INT) {
DEBUGMSGTL(("mymib", "wrong value %x", intval));
return SNMP_ERR_WRONGVALUE;
}
/*
*/
break;
case RESERVE2:
/*
* This is conventially where any necesary
* resources are allocated (e.g. calls to malloc)
* Here, we are using static variables
* so don't need to worry about this.
*/
break;
case FREE:
/*
* This is where any of the above resources
* are freed again (because one of the other
* values being SET failed for some reason).
* Again, since we are using static variables
* we don't need to worry about this either.
*/
break;
case ACTION:
/*
* Set the variable as requested.
* Note that this may need to be reversed,
* so save any information needed to do this.
*/
old_intval = mymib_int;
mymib_int = intval;
break;
case UNDO:
/*
* Something failed, so re-set the
* variable to its previous value
* (and free any allocated resources).
*/
mymib_int = old_intval;
break;
case 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.
*
* In this case, there's nothing to do.
*/
break;
}
return SNMP_ERR_NOERROR;
}
int
write_mymibtrap(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len)
{
long intval;
DEBUGMSGTL(("mymib", "write_mymibtrap entered: action=%d\n",
action));
switch (action) {
case RESERVE1:
/*
* The only acceptable value is the integer 1
*/
if (var_val_type != ASN_INTEGER) {
DEBUGMSGTL(("mymib", "%x not integer type", var_val_type));
return SNMP_ERR_WRONGTYPE;
}
if (var_val_len > sizeof(long)) {
DEBUGMSGTL(("mymib", "wrong length %x", var_val_len));
return SNMP_ERR_WRONGLENGTH;
}
intval = *((long *) var_val);
if (intval != 1) {
DEBUGMSGTL(("mymib", "wrong value %x", intval));
return SNMP_ERR_WRONGVALUE;
}
break;
case RESERVE2:
/*
* No resources are required....
*/
break;
case FREE:
/*
* ... so no resources need be freed
*/
break;
case ACTION:
/*
* Having triggered the sending of a trap,
* it would be impossible to revoke this,
* so we can't actually invoke the action here.
*/
break;
case UNDO:
/*
* We haven't done anything yet,
* so there's nothing to undo
*/
break;
case COMMIT:
/*
* Everything else worked, so it's now safe
* to trigger the trap.
* Note that this is *only* acceptable since
* the trap sending routines are "failsafe".
* (In fact, they can fail, but they return no
* indication of this, which is the next best thing!)
*/
DEBUGMSGTL(("mymib", "write_mymibtrap sending the trap\n",
action));
send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 99);
DEBUGMSGTL(("mymib", "write_mymibtrap trap sent\n", action));
break;
}
return SNMP_ERR_NOERROR;
}
/*
* this documents how to send a SNMPv2 (and higher) trap via the
* send_v2trap() API.
*
* Coding SNMP-v2 Trap:
*
* The SNMPv2-Trap PDU contains at least a pair of object names and
* values: - sysUpTime.0 whose value is the time in hundredths of a
* second since the netwok management portion of system was last
* reinitialized. - snmpTrapOID.0 which is part of the trap group SNMPv2
* MIB whose value is the object-id of the specific trap you have defined
* in your own MIB. Other variables can be added to caracterize the
* trap.
*
* The function send_v2trap adds automaticallys the two objects but the
* value of snmpTrapOID.0 is 0.0 by default. If you want to add your trap
* name, you have to reconstruct this object and to add your own
* variable.
*
*/
int
write_mymibtrap2(int action,
u_char * var_val,
u_char var_val_type,
size_t var_val_len,
u_char * statP, oid * name, size_t name_len)
{
long intval;
/*
* these variales will be used when we send the trap
*/
oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; /* snmpTrapOID.0 */
oid demo_trap[] = { 1, 3, 6, 1, 4, 1, 2021, 13, 990 }; /*demo-trap */
oid mymib_string_oid[] =
{ 1, 3, 6, 1, 4, 1, 2021, 254, 1, 0 };
static netsnmp_variable_list var_trap;
static netsnmp_variable_list var_obj;
DEBUGMSGTL(("mymib", "write_mymibtrap2 entered: action=%d\n",
action));
switch (action) {
case RESERVE1:
/*
* The only acceptable value is the integer 1
*/
if (var_val_type != ASN_INTEGER) {
DEBUGMSGTL(("mymib", "%x not integer type", var_val_type));
return SNMP_ERR_WRONGTYPE;
}
if (var_val_len > sizeof(long)) {
DEBUGMSGTL(("mymib", "wrong length %x", var_val_len));
return SNMP_ERR_WRONGLENGTH;
}
intval = *((long *) var_val);
if (intval != 1) {
DEBUGMSGTL(("mymib", "wrong value %x", intval));
return SNMP_ERR_WRONGVALUE;
}
break;
case RESERVE2:
/*
* No resources are required....
*/
break;
case FREE:
/*
* ... so no resources need be freed
*/
break;
case ACTION:
/*
* Having triggered the sending of a trap,
* it would be impossible to revoke this,
* so we can't actually invoke the action here.
*/
break;
case UNDO:
/*
* We haven't done anything yet,
* so there's nothing to undo
*/
break;
case COMMIT:
/*
* Everything else worked, so it's now safe
* to trigger the trap.
* Note that this is *only* acceptable since
* the trap sending routines are "failsafe".
* (In fact, they can fail, but they return no
* indication of this, which is the next best thing!)
*/
/*
* trap definition objects
*/
var_trap.next_variable = &var_obj; /* next variable */
var_trap.name = objid_snmptrap; /* snmpTrapOID.0 */
var_trap.name_length = sizeof(objid_snmptrap) / sizeof(oid); /* number of sub-ids */
var_trap.type = ASN_OBJECT_ID;
var_trap.val.objid = demo_trap; /* demo-trap objid */
var_trap.val_len = sizeof(demo_trap); /* length in bytes (not number of subids!) */
/*
* additional objects
*/
var_obj.next_variable = NULL; /* No more variables after this one */
var_obj.name = mymib_string_oid;
var_obj.name_length = sizeof(mymib_string_oid) / sizeof(oid); /* number of sub-ids */
var_obj.type = ASN_OCTET_STR; /* type of variable */
var_obj.val.string = mymib_str; /* value */
var_obj.val_len = strlen(mymib_str);
DEBUGMSGTL(("mymib", "write_mymibtrap2 sending the v2 trap\n",
action));
send_v2trap(&var_trap);
DEBUGMSGTL(("mymib", "write_mymibtrap2 v2 trap sent\n",
action));
break;
}
return SNMP_ERR_NOERROR;
}
---