example.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:23k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  *  Template MIB group implementation - example.c
  3.  *
  4.  */
  5. /*
  6.  * include important headers 
  7.  */
  8. #include <net-snmp/net-snmp-config.h>
  9. #if HAVE_STDLIB_H
  10. #include <stdlib.h>
  11. #endif
  12. #if HAVE_STRING_H
  13. #include <string.h>
  14. #else
  15. #include <strings.h>
  16. #endif
  17. /*
  18.  * needed by util_funcs.h 
  19.  */
  20. #if TIME_WITH_SYS_TIME
  21. # ifdef WIN32
  22. #  include <sys/timeb.h>
  23. # else
  24. #  include <sys/time.h>
  25. # endif
  26. # include <time.h>
  27. #else
  28. # if HAVE_SYS_TIME_H
  29. #  include <sys/time.h>
  30. # else
  31. #  include <time.h>
  32. # endif
  33. #endif
  34. #if HAVE_WINSOCK_H
  35. #include <winsock.h>
  36. #endif
  37. #if HAVE_NETINET_IN_H
  38. #include <netinet/in.h>
  39. #endif
  40. #include <net-snmp/net-snmp-includes.h>
  41. #include <net-snmp/agent/net-snmp-agent-includes.h>
  42. /*
  43.  * header_generic() comes from here 
  44.  */
  45. #include "util_funcs.h"
  46. /*
  47.  * include our .h file 
  48.  */
  49. #include "example.h"
  50.    /*
  51.     *  Certain objects can be set via configuration file directives.
  52.     *  These variables hold the values for such objects, as they need to
  53.     *   be accessible to both the config handlers, and the callback routine.
  54.     */
  55. #define EXAMPLE_STR_LEN 300
  56. #define EXAMPLE_STR_DEFAULT "life the universe and everything"
  57. int             example_int = 42;
  58. char            example_str[EXAMPLE_STR_LEN];
  59.         /*
  60.          * Forward declarations for the config handlers 
  61.          */
  62. void            example_parse_config_exampleint(const char *token,
  63.                                                 char *cptr);
  64. void            example_parse_config_examplestr(const char *token,
  65.                                                 char *cptr);
  66. void            example_free_config_exampleint(void);
  67. void            example_free_config_examplestr(void);
  68.         /*********************
  69.  *
  70.  *  Initialisation & common implementation functions
  71.  *
  72.  *********************/
  73.     /*
  74.      * This array structure defines a representation of the
  75.      *  MIB being implemented.
  76.      *
  77.      * The type of the array is 'struct variableN', where N is
  78.      *  large enough to contain the longest OID sub-component
  79.      *  being loaded.  This will normally be the maximum value
  80.      *  of the fifth field in each line.  In this case, the second
  81.      *  and third entries are both of size 2, so we're using
  82.      *  'struct variable2'
  83.      *
  84.      * The supported values for N are listed in <agent/var_struct.h>
  85.      *  If the value you need is not listed there, simply use the
  86.      *  next largest that is.
  87.      *
  88.      * The format of each line is as follows
  89.      *  (using the first entry as an example):
  90.      *      1: EXAMPLESTRING:
  91.      *          The magic number defined in the example header file.
  92.      *          This is passed to the callback routine and is used
  93.      *            to determine which object is being queried.
  94.      *      2: ASN_OCTET_STR:
  95.      *          The type of the object.
  96.      *          Valid types are listed in <snmp_impl.h>
  97.      *      3: RONLY (or RWRITE):
  98.      *          Whether this object can be SET or not.
  99.      *      4: var_example:
  100.      *          The callback routine, used when the object is queried.
  101.      *          This will usually be the same for all objects in a module
  102.      *            and is typically defined later in this file.
  103.      *      5: 1:
  104.      *          The length of the OID sub-component (the next field)
  105.      *      6: {1}:
  106.      *          The OID sub-components of this entry.
  107.      *          In other words, the bits of the full OID that differ
  108.      *            between the various entries of this array.
  109.      *          This value is appended to the common prefix (defined later)
  110.      *            to obtain the full OID of each entry.
  111.      */
  112. struct variable2 example_variables[] = {
  113.     {EXAMPLESTRING, ASN_OCTET_STR, RONLY, var_example, 1, {1}},
  114.     {EXAMPLEINTEGER, ASN_INTEGER, RWRITE, var_example, 2, {2, 1}},
  115.     {EXAMPLEOBJECTID, ASN_OBJECT_ID, RONLY, var_example, 2, {2, 2}},
  116.     {EXAMPLETIMETICKS, ASN_TIMETICKS, RONLY, var_example, 1, {3}},
  117.     {EXAMPLEIPADDRESS, ASN_IPADDRESS, RONLY, var_example, 1, {4}},
  118.     {EXAMPLECOUNTER, ASN_COUNTER, RONLY, var_example, 1, {5}},
  119.     {EXAMPLEGAUGE, ASN_GAUGE, RONLY, var_example, 1, {6}},
  120.     {EXAMPLETRIGGERTRAP, ASN_INTEGER, RWRITE, var_example, 1, {7}},
  121.     {EXAMPLETRIGGERTRAP2, ASN_INTEGER, RWRITE, var_example, 1, {8}}
  122. };
  123.     /*
  124.      * This array defines the OID of the top of the mib tree that we're
  125.      *  registering underneath.
  126.      * Note that this needs to be the correct size for the OID being 
  127.      *  registered, so that the length of the OID can be calculated.
  128.      *  The format given here is the simplest way to achieve this.
  129.      */
  130. oid             example_variables_oid[] = { 1, 3, 6, 1, 4, 1, 2021, 254 };
  131.     /*
  132.      * This function is called at the time the agent starts up
  133.      *  to do any initializations that might be required.
  134.      *
  135.      * In theory it is optional and can be omitted if no
  136.      *  initialization is needed.  In practise, every module
  137.      *  will need to register itself (or the objects being
  138.      *  implemented will not appear in the MIB tree), and this
  139.      *  registration is typically done here.
  140.      *
  141.      * If this function is added or removed, you must re-run
  142.      *  the configure script, to detect this change.
  143.      */
  144. void
  145. init_example(void)
  146. {
  147.     /*
  148.      * Register ourselves with the agent to handle our mib tree.
  149.      * The arguments are:
  150.      *    descr:   A short description of the mib group being loaded.
  151.      *    var:     The variable structure to load.
  152.      *                  (the name of the variable structure defined above)
  153.      *    vartype: The type of this variable structure
  154.      *    theoid:  The OID pointer this MIB is being registered underneath.
  155.      */
  156.     REGISTER_MIB("example", example_variables, variable2,
  157.                  example_variables_oid);
  158.     /*
  159.      *  Register config handlers for the two objects that can be set
  160.      *   via configuration file directive.
  161.      *  Also set a default value for the string object.  Note that the
  162.      *   example integer variable was initialised above.
  163.      */
  164.     strncpy(example_str, EXAMPLE_STR_DEFAULT, EXAMPLE_STR_LEN);
  165.     snmpd_register_config_handler("exampleint",
  166.                                   example_parse_config_exampleint,
  167.                                   example_free_config_exampleint,
  168.                                   "exampleint value");
  169.     snmpd_register_config_handler("examplestr",
  170.                                   example_parse_config_examplestr,
  171.                                   example_free_config_examplestr,
  172.                                   "examplestr value");
  173.     snmpd_register_config_handler("examplestring",
  174.                                   example_parse_config_examplestr,
  175.                                   example_free_config_examplestr,
  176.                                   "examplestring value");
  177.     /*
  178.      * One common requirement is to read values from the kernel.
  179.      * This is usually initialised here, to speed up access when the
  180.      *  information is read in, as a response to an incoming request.
  181.      *
  182.      * This module doesn't actually use this mechanism,
  183.      * so this call is commented out here.
  184.      */
  185.     /*
  186.      * auto_nlist( "example_symbol", 0, 0 ); 
  187.      */
  188. }
  189.         /*********************
  190.  *
  191.  *  Configuration file handling functions
  192.  *
  193.  *********************/
  194. void
  195. example_parse_config_exampleint(const char *token, char *cptr)
  196. {
  197.     example_int = atoi(cptr);
  198. }
  199. void
  200. example_parse_config_examplestr(const char *token, char *cptr)
  201. {
  202.     /*
  203.      * Make sure the string fits in the space allocated for it.
  204.      */
  205.     if (strlen(cptr) < EXAMPLE_STR_LEN)
  206.         strcpy(example_str, cptr);
  207.     else {
  208.         /*
  209.          * Truncate the string if necessary.
  210.          * An alternative approach would be to log an error,
  211.          *  and discard this value altogether.
  212.          */
  213.         strncpy(example_str, cptr, EXAMPLE_STR_LEN - 4);
  214.         example_str[EXAMPLE_STR_LEN - 4] = 0;
  215.         strcat(example_str, "...");
  216.         example_str[EXAMPLE_STR_LEN - 1] = 0;
  217.     }
  218. }
  219.         /*
  220.          * We don't need to do anything special when closing down 
  221.          */
  222. void
  223. example_free_config_exampleint(void)
  224. {
  225. }
  226. void
  227. example_free_config_examplestr(void)
  228. {
  229. }
  230.         /*********************
  231.  *
  232.  *  System specific implementation functions
  233.  *
  234.  *********************/
  235.     /*
  236.      * Define the callback function used in the example_variables structure.
  237.      * This is called whenever an incoming request refers to an object
  238.      *  within this sub-tree.
  239.      *
  240.      * Four of the parameters are used to pass information in.
  241.      * These are:
  242.      *    vp      The entry from the 'example_variables' array for the
  243.      *             object being queried.
  244.      *    name    The OID from the request.
  245.      *    length  The length of this OID.
  246.      *    exact   A flag to indicate whether this is an 'exact' request
  247.      *             (GET/SET) or an 'inexact' one (GETNEXT/GETBULK).
  248.      *
  249.      * Four of the parameters are used to pass information back out.
  250.      * These are:
  251.      *    name     The OID being returned.
  252.      *    length   The length of this OID.
  253.      *    var_len  The length of the answer being returned.
  254.      *    write_method   A pointer to the SET function for this object.
  255.      *
  256.      * Note that name & length serve a dual purpose in both roles.
  257.      */
  258. u_char         *
  259. var_example(struct variable *vp,
  260.             oid * name,
  261.             size_t * length,
  262.             int exact, size_t * var_len, WriteMethod ** write_method)
  263. {
  264.     /*
  265.      *  The result returned from this function needs to be a pointer to
  266.      *    static data (so that it can be accessed from outside).
  267.      *  Define suitable variables for any type of data we may return.
  268.      */
  269.     static char     string[EXAMPLE_STR_LEN];    /* for EXAMPLESTRING   */
  270.     static oid      oid_ret[8]; /* for EXAMPLEOBJECTID */
  271.     static long     long_ret;   /* for everything else */
  272.     /*
  273.      * Before returning an answer, we need to check that the request
  274.      *  refers to a valid instance of this object.  The utility routine
  275.      *  'header_generic' can be used to do this for scalar objects.
  276.      *
  277.      * This routine 'header_simple_table' does the same thing for "simple"
  278.      *  tables. (See the AGENT.txt file for the definition of a simple table).
  279.      *
  280.      * Both these utility routines also set up default values for the
  281.      *  return arguments (assuming the check succeeded).
  282.      * The name and length are set suitably for the current object,
  283.      *  var_len assumes that the result is an integer of some form,
  284.      *  and write_method assumes that the object cannot be set.
  285.      *
  286.      * If these assumptions are correct, this callback routine simply
  287.      * needs to return a pointer to the appropriate value (using 'long_ret').
  288.      * Otherwise, 'var_len' and/or 'write_method' should be set suitably.
  289.      */
  290.     DEBUGMSGTL(("example", "var_example enteredn"));
  291.     if (header_generic(vp, name, length, exact, var_len, write_method) ==
  292.         MATCH_FAILED)
  293.         return NULL;
  294.     /*
  295.      * Many object will need to obtain data from the operating system in
  296.      *  order to return the appropriate value.  Typically, this is done
  297.      *  here - immediately following the 'header' call, and before the
  298.      *  switch statement. This is particularly appropriate if a single 
  299.      *  interface call can return data for all the objects supported.
  300.      *
  301.      * This example module does not rely on external data, so no such
  302.      *  calls are needed in this case.  
  303.      */
  304.     /*
  305.      * Now use the magic number from the variable pointer 'vp' to
  306.      *  select the particular object being queried.
  307.      * In each case, one of the static objects is set up with the
  308.      *  appropriate information, and returned mapped to a 'u_char *'
  309.      */
  310.     switch (vp->magic) {
  311.     case EXAMPLESTRING:
  312.         sprintf(string, example_str);
  313.         /*
  314.          * Note that the assumption that the answer will be an
  315.          *  integer does not hold true in this case, so the length
  316.          *  of the answer needs to be set explicitly.           
  317.          */
  318.         *var_len = strlen(string);
  319.         return (u_char *) string;
  320.     case EXAMPLEINTEGER:
  321.         /*
  322.          * Here the length assumption is correct, but the
  323.          *  object is writeable, so we need to set the
  324.          *  write_method pointer as well as the current value.
  325.          */
  326.         long_ret = example_int;
  327.         *write_method = write_exampleint;
  328.         return (u_char *) & long_ret;
  329.     case EXAMPLEOBJECTID:
  330.         oid_ret[0] = 1;
  331.         oid_ret[1] = 3;
  332.         oid_ret[2] = 6;
  333.         oid_ret[3] = 1;
  334.         oid_ret[4] = 4;
  335.         oid_ret[5] = oid_ret[6] = oid_ret[7] = 42;
  336.         /*
  337.          * Again, the assumption regarding the answer length is wrong.
  338.          */
  339.         *var_len = 8 * sizeof(oid);
  340.         return (u_char *) oid_ret;
  341.     case EXAMPLETIMETICKS:
  342.         /*
  343.          * Here both assumptions are correct,
  344.          *  so we just need to set up the answer.
  345.          */
  346.         long_ret = 363136200;   /* 42 days, 42 minutes and 42.0 seconds */
  347.         return (u_char *) & long_ret;
  348.     case EXAMPLEIPADDRESS:
  349.         /*
  350.          * ipaddresses get returned as a long.  ick 
  351.          */
  352.         /*
  353.          * we're returning 127.0.0.1 
  354.          */
  355.         long_ret = ntohl(INADDR_LOOPBACK);
  356.         return (u_char *) & long_ret;
  357.     case EXAMPLECOUNTER:
  358.         long_ret = 42;
  359.         return (u_char *) & long_ret;
  360.     case EXAMPLEGAUGE:
  361.         long_ret = 42;          /* Do we detect a theme running through these answers? */
  362.         return (u_char *) & long_ret;
  363.     case EXAMPLETRIGGERTRAP:
  364.         /*
  365.          * This object is essentially "write-only".
  366.          * It only exists to trigger the sending of a trap.
  367.          * Reading it will always return 0.
  368.          */
  369.         long_ret = 0;
  370.         *write_method = write_exampletrap;
  371.         return (u_char *) & long_ret;
  372.     case EXAMPLETRIGGERTRAP2:
  373.         /*
  374.          * This object is essentially "write-only".
  375.          * It only exists to trigger the sending of a v2 trap.
  376.          * Reading it will always return 0.
  377.          */
  378.         long_ret = 0;
  379.         *write_method = write_exampletrap2;
  380.         return (u_char *) & long_ret;
  381.     default:
  382.         /*
  383.          *  This will only be triggered if there's a problem with
  384.          *   the coding of the module.  SNMP requests that reference
  385.          *   a non-existant OID will be directed elsewhere.
  386.          *  If this branch is reached, log an error, so that
  387.          *   the problem can be investigated.
  388.          */
  389.         DEBUGMSGTL(("snmpd", "unknown sub-id %d in examples/var_examplen",
  390.                     vp->magic));
  391.     }
  392.     /*
  393.      * If we fall through to here, fail by returning NULL.
  394.      * This is essentially a continuation of the 'default' case above.
  395.      */
  396.     return NULL;
  397. }
  398.         /*********************
  399.  *
  400.  *  Writeable object SET handling routines
  401.  *
  402.  *********************/
  403. int
  404. write_exampleint(int action,
  405.                  u_char * var_val,
  406.                  u_char var_val_type,
  407.                  size_t var_val_len,
  408.                  u_char * statP, oid * name, size_t name_len)
  409. {
  410.     /*
  411.      * Define an arbitrary maximum permissible value 
  412.      */
  413. #define MAX_EXAMPLE_INT 100
  414.     static long     intval;
  415.     static long     old_intval;
  416.     switch (action) {
  417.     case RESERVE1:
  418.         /*
  419.          *  Check that the value being set is acceptable
  420.          */
  421.         if (var_val_type != ASN_INTEGER) {
  422.             DEBUGMSGTL(("example", "%x not integer type", var_val_type));
  423.             return SNMP_ERR_WRONGTYPE;
  424.         }
  425.         if (var_val_len > sizeof(long)) {
  426.             DEBUGMSGTL(("example", "wrong length %x", var_val_len));
  427.             return SNMP_ERR_WRONGLENGTH;
  428.         }
  429.         intval = *((long *) var_val);
  430.         if (intval > MAX_EXAMPLE_INT) {
  431.             DEBUGMSGTL(("example", "wrong value %x", intval));
  432.             return SNMP_ERR_WRONGVALUE;
  433.         }
  434.         break;
  435.     case RESERVE2:
  436.         /*
  437.          *  This is conventially where any necesary
  438.          *   resources are allocated (e.g. calls to malloc)
  439.          *  Here, we are using static variables
  440.          *   so don't need to worry about this.
  441.          */
  442.         break;
  443.     case FREE:
  444.         /*
  445.          *  This is where any of the above resources
  446.          *   are freed again (because one of the other
  447.          *   values being SET failed for some reason).
  448.          *  Again, since we are using static variables
  449.          *   we don't need to worry about this either.
  450.          */
  451.         break;
  452.     case ACTION:
  453.         /*
  454.          *  Set the variable as requested.
  455.          *   Note that this may need to be reversed,
  456.          *   so save any information needed to do this.
  457.          */
  458.         old_intval = example_int;
  459.         example_int = intval;
  460.         break;
  461.     case UNDO:
  462.         /*
  463.          *  Something failed, so re-set the
  464.          *   variable to its previous value
  465.          *  (and free any allocated resources).
  466.          */
  467.         example_int = old_intval;
  468.         break;
  469.     case COMMIT:
  470.         /*
  471.          *  Everything worked, so we can discard any
  472.          *   saved information, and make the change
  473.          *   permanent (e.g. write to the config file).
  474.          *  We also free any allocated resources.
  475.          *
  476.          *  In this case, there's nothing to do.
  477.          */
  478.         break;
  479.     }
  480.     return SNMP_ERR_NOERROR;
  481. }
  482. int
  483. write_exampletrap(int action,
  484.                   u_char * var_val,
  485.                   u_char var_val_type,
  486.                   size_t var_val_len,
  487.                   u_char * statP, oid * name, size_t name_len)
  488. {
  489.     long            intval;
  490.     DEBUGMSGTL(("example", "write_exampletrap entered: action=%dn",
  491.                 action));
  492.     switch (action) {
  493.     case RESERVE1:
  494.         /*
  495.          *  The only acceptable value is the integer 1
  496.          */
  497.         if (var_val_type != ASN_INTEGER) {
  498.             DEBUGMSGTL(("example", "%x not integer type", var_val_type));
  499.             return SNMP_ERR_WRONGTYPE;
  500.         }
  501.         if (var_val_len > sizeof(long)) {
  502.             DEBUGMSGTL(("example", "wrong length %x", var_val_len));
  503.             return SNMP_ERR_WRONGLENGTH;
  504.         }
  505.         intval = *((long *) var_val);
  506.         if (intval != 1) {
  507.             DEBUGMSGTL(("example", "wrong value %x", intval));
  508.             return SNMP_ERR_WRONGVALUE;
  509.         }
  510.         break;
  511.     case RESERVE2:
  512.         /*
  513.          * No resources are required.... 
  514.          */
  515.         break;
  516.     case FREE:
  517.         /*
  518.          * ... so no resources need be freed 
  519.          */
  520.         break;
  521.     case ACTION:
  522.         /*
  523.          *  Having triggered the sending of a trap,
  524.          *   it would be impossible to revoke this,
  525.          *   so we can't actually invoke the action here.
  526.          */
  527.         break;
  528.     case UNDO:
  529.         /*
  530.          * We haven't done anything yet,
  531.          * so there's nothing to undo 
  532.          */
  533.         break;
  534.     case COMMIT:
  535.         /*
  536.          *  Everything else worked, so it's now safe
  537.          *   to trigger the trap.
  538.          *  Note that this is *only* acceptable since
  539.          *   the trap sending routines are "failsafe".
  540.          *  (In fact, they can fail, but they return no
  541.          *   indication of this, which is the next best thing!)
  542.          */
  543.         DEBUGMSGTL(("example", "write_exampletrap sending the trapn",
  544.                     action));
  545.         send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 99);
  546.         DEBUGMSGTL(("example", "write_exampletrap trap sentn", action));
  547.         break;
  548.     }
  549.     return SNMP_ERR_NOERROR;
  550. }
  551. /*
  552.  * this documents how to send a SNMPv2 (and higher) trap via the
  553.  * send_v2trap() API.
  554.  * 
  555.  * Coding SNMP-v2 Trap:
  556.  * 
  557.  * The SNMPv2-Trap PDU contains at least a pair of object names and
  558.  * values: - sysUpTime.0 whose value is the time in hundredths of a
  559.  * second since the netwok management portion of system was last
  560.  * reinitialized.  - snmpTrapOID.0 which is part of the trap group SNMPv2
  561.  * MIB whose value is the object-id of the specific trap you have defined
  562.  * in your own MIB.  Other variables can be added to caracterize the
  563.  * trap.
  564.  * 
  565.  * The function send_v2trap adds automaticallys the two objects but the
  566.  * value of snmpTrapOID.0 is 0.0 by default. If you want to add your trap
  567.  * name, you have to reconstruct this object and to add your own
  568.  * variable.
  569.  * 
  570.  */
  571. int
  572. write_exampletrap2(int action,
  573.                    u_char * var_val,
  574.                    u_char var_val_type,
  575.                    size_t var_val_len,
  576.                    u_char * statP, oid * name, size_t name_len)
  577. {
  578.     long            intval;
  579.     /*
  580.      * these variales will be used when we send the trap 
  581.      */
  582.     oid             objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };     /* snmpTrapOID.0 */
  583.     oid             demo_trap[] = { 1, 3, 6, 1, 4, 1, 2021, 13, 990 };  /*demo-trap */
  584.     oid             example_string_oid[] =
  585.         { 1, 3, 6, 1, 4, 1, 2021, 254, 1, 0 };
  586.     static netsnmp_variable_list var_trap;
  587.     static netsnmp_variable_list var_obj;
  588.     DEBUGMSGTL(("example", "write_exampletrap2 entered: action=%dn",
  589.                 action));
  590.     switch (action) {
  591.     case RESERVE1:
  592.         /*
  593.          *  The only acceptable value is the integer 1
  594.          */
  595.         if (var_val_type != ASN_INTEGER) {
  596.             DEBUGMSGTL(("example", "%x not integer type", var_val_type));
  597.             return SNMP_ERR_WRONGTYPE;
  598.         }
  599.         if (var_val_len > sizeof(long)) {
  600.             DEBUGMSGTL(("example", "wrong length %x", var_val_len));
  601.             return SNMP_ERR_WRONGLENGTH;
  602.         }
  603.         intval = *((long *) var_val);
  604.         if (intval != 1) {
  605.             DEBUGMSGTL(("example", "wrong value %x", intval));
  606.             return SNMP_ERR_WRONGVALUE;
  607.         }
  608.         break;
  609.     case RESERVE2:
  610.         /*
  611.          * No resources are required.... 
  612.          */
  613.         break;
  614.     case FREE:
  615.         /*
  616.          * ... so no resources need be freed 
  617.          */
  618.         break;
  619.     case ACTION:
  620.         /*
  621.          *  Having triggered the sending of a trap,
  622.          *   it would be impossible to revoke this,
  623.          *   so we can't actually invoke the action here.
  624.          */
  625.         break;
  626.     case UNDO:
  627.         /*
  628.          * We haven't done anything yet,
  629.          * so there's nothing to undo 
  630.          */
  631.         break;
  632.     case COMMIT:
  633.         /*
  634.          *  Everything else worked, so it's now safe
  635.          *   to trigger the trap.
  636.          *  Note that this is *only* acceptable since
  637.          *   the trap sending routines are "failsafe".
  638.          *  (In fact, they can fail, but they return no
  639.          *   indication of this, which is the next best thing!)
  640.          */
  641.         /*
  642.          * trap definition objects 
  643.          */
  644.         var_trap.next_variable = &var_obj;      /* next variable */
  645.         var_trap.name = objid_snmptrap; /* snmpTrapOID.0 */
  646.         var_trap.name_length = sizeof(objid_snmptrap) / sizeof(oid);    /* number of sub-ids */
  647.         var_trap.type = ASN_OBJECT_ID;
  648.         var_trap.val.objid = demo_trap; /* demo-trap objid */
  649.         var_trap.val_len = sizeof(demo_trap);   /* length in bytes (not number of subids!) */
  650.         /*
  651.          * additional objects 
  652.          */
  653.         var_obj.next_variable = NULL;   /* No more variables after this one */
  654.         var_obj.name = example_string_oid;
  655.         var_obj.name_length = sizeof(example_string_oid) / sizeof(oid); /* number of sub-ids */
  656.         var_obj.type = ASN_OCTET_STR;   /* type of variable */
  657.         var_obj.val.string = example_str;       /* value */
  658.         var_obj.val_len = strlen(example_str);
  659.         DEBUGMSGTL(("example", "write_exampletrap2 sending the v2 trapn",
  660.                     action));
  661.         send_v2trap(&var_trap);
  662.         DEBUGMSGTL(("example", "write_exampletrap2 v2 trap sentn",
  663.                     action));
  664.         break;
  665.     }
  666.     return SNMP_ERR_NOERROR;
  667. }