example.c

00001 /*
00002  *  Template MIB group implementation - example.c
00003  *
00004  */
00005 
00006 /*
00007  * include important headers 
00008  */
00009 #include <net-snmp/net-snmp-config.h>
00010 #if HAVE_STDLIB_H
00011 #include <stdlib.h>
00012 #endif
00013 #if HAVE_STRING_H
00014 #include <string.h>
00015 #else
00016 #include <strings.h>
00017 #endif
00018 
00019 /*
00020  * needed by util_funcs.h 
00021  */
00022 #if TIME_WITH_SYS_TIME
00023 # ifdef WIN32
00024 #  include <sys/timeb.h>
00025 # else
00026 #  include <sys/time.h>
00027 # endif
00028 # include <time.h>
00029 #else
00030 # if HAVE_SYS_TIME_H
00031 #  include <sys/time.h>
00032 # else
00033 #  include <time.h>
00034 # endif
00035 #endif
00036 
00037 #if HAVE_WINSOCK_H
00038 #include <winsock.h>
00039 #endif
00040 #if HAVE_NETINET_IN_H
00041 #include <netinet/in.h>
00042 #endif
00043 
00044 #include <net-snmp/net-snmp-includes.h>
00045 #include <net-snmp/agent/net-snmp-agent-includes.h>
00046 
00047 /*
00048  * header_generic() comes from here 
00049  */
00050 #include "util_funcs.h"
00051 
00052 /*
00053  * include our .h file 
00054  */
00055 #include "example.h"
00056 
00057 
00058    /*
00059     *  Certain objects can be set via configuration file directives.
00060     *  These variables hold the values for such objects, as they need to
00061     *   be accessible to both the config handlers, and the callback routine.
00062     */
00063 #define EXAMPLE_STR_LEN 300
00064 #define EXAMPLE_STR_DEFAULT     "life the universe and everything"
00065 int             example_int = 42;
00066 char            example_str[EXAMPLE_STR_LEN];
00067 
00068         /*
00069          * Forward declarations for the config handlers 
00070          */
00071 void            example_parse_config_exampleint(const char *token,
00072                                                 char *cptr);
00073 void            example_parse_config_examplestr(const char *token,
00074                                                 char *cptr);
00075 void            example_free_config_exampleint(void);
00076 void            example_free_config_examplestr(void);
00077 
00078 
00079         /*********************
00080          *
00081          *  Initialisation & common implementation functions
00082          *
00083          *********************/
00084 
00085     /*
00086      * This array structure defines a representation of the
00087      *  MIB being implemented.
00088      *
00089      * The type of the array is 'struct variableN', where N is
00090      *  large enough to contain the longest OID sub-component
00091      *  being loaded.  This will normally be the maximum value
00092      *  of the fifth field in each line.  In this case, the second
00093      *  and third entries are both of size 2, so we're using
00094      *  'struct variable2'
00095      *
00096      * The supported values for N are listed in <agent/var_struct.h>
00097      *  If the value you need is not listed there, simply use the
00098      *  next largest that is.
00099      *
00100      * The format of each line is as follows
00101      *  (using the first entry as an example):
00102      *      1: EXAMPLESTRING:
00103      *          The magic number defined in the example header file.
00104      *          This is passed to the callback routine and is used
00105      *            to determine which object is being queried.
00106      *      2: ASN_OCTET_STR:
00107      *          The type of the object.
00108      *          Valid types are listed in <snmp_impl.h>
00109      *      3: RONLY (or RWRITE):
00110      *          Whether this object can be SET or not.
00111      *      4: var_example:
00112      *          The callback routine, used when the object is queried.
00113      *          This will usually be the same for all objects in a module
00114      *            and is typically defined later in this file.
00115      *      5: 1:
00116      *          The length of the OID sub-component (the next field)
00117      *      6: {1}:
00118      *          The OID sub-components of this entry.
00119      *          In other words, the bits of the full OID that differ
00120      *            between the various entries of this array.
00121      *          This value is appended to the common prefix (defined later)
00122      *            to obtain the full OID of each entry.
00123      */
00124 struct variable2 example_variables[] = {
00125     {EXAMPLESTRING, ASN_OCTET_STR, RONLY, var_example, 1, {1}},
00126     {EXAMPLEINTEGER, ASN_INTEGER, RWRITE, var_example, 2, {2, 1}},
00127     {EXAMPLEOBJECTID, ASN_OBJECT_ID, RONLY, var_example, 2, {2, 2}},
00128     {EXAMPLETIMETICKS, ASN_TIMETICKS, RONLY, var_example, 1, {3}},
00129     {EXAMPLEIPADDRESS, ASN_IPADDRESS, RONLY, var_example, 1, {4}},
00130     {EXAMPLECOUNTER, ASN_COUNTER, RONLY, var_example, 1, {5}},
00131     {EXAMPLEGAUGE, ASN_GAUGE, RONLY, var_example, 1, {6}},
00132     {EXAMPLETRIGGERTRAP, ASN_INTEGER, RWRITE, var_example, 1, {7}},
00133     {EXAMPLETRIGGERTRAP2, ASN_INTEGER, RWRITE, var_example, 1, {8}}
00134 };
00135 
00136     /*
00137      * This array defines the OID of the top of the mib tree that we're
00138      *  registering underneath.
00139      * Note that this needs to be the correct size for the OID being 
00140      *  registered, so that the length of the OID can be calculated.
00141      *  The format given here is the simplest way to achieve this.
00142      */
00143 oid             example_variables_oid[] = { 1, 3, 6, 1, 4, 1, 2021, 254 };
00144 
00145 
00146 
00147     /*
00148      * This function is called at the time the agent starts up
00149      *  to do any initializations that might be required.
00150      *
00151      * In theory it is optional and can be omitted if no
00152      *  initialization is needed.  In practise, every module
00153      *  will need to register itself (or the objects being
00154      *  implemented will not appear in the MIB tree), and this
00155      *  registration is typically done here.
00156      *
00157      * If this function is added or removed, you must re-run
00158      *  the configure script, to detect this change.
00159      */
00160 void
00161 init_example(void)
00162 {
00163     /*
00164      * Register ourselves with the agent to handle our mib tree.
00165      * The arguments are:
00166      *    descr:   A short description of the mib group being loaded.
00167      *    var:     The variable structure to load.
00168      *                  (the name of the variable structure defined above)
00169      *    vartype: The type of this variable structure
00170      *    theoid:  The OID pointer this MIB is being registered underneath.
00171      */
00172     REGISTER_MIB("example", example_variables, variable2,
00173                  example_variables_oid);
00174 
00175 
00176     /*
00177      *  Register config handlers for the two objects that can be set
00178      *   via configuration file directive.
00179      *  Also set a default value for the string object.  Note that the
00180      *   example integer variable was initialised above.
00181      */
00182     strncpy(example_str, EXAMPLE_STR_DEFAULT, EXAMPLE_STR_LEN);
00183 
00184     snmpd_register_config_handler("exampleint",
00185                                   example_parse_config_exampleint,
00186                                   example_free_config_exampleint,
00187                                   "exampleint value");
00188     snmpd_register_config_handler("examplestr",
00189                                   example_parse_config_examplestr,
00190                                   example_free_config_examplestr,
00191                                   "examplestr value");
00192     snmpd_register_config_handler("examplestring",
00193                                   example_parse_config_examplestr,
00194                                   example_free_config_examplestr,
00195                                   "examplestring value");
00196 
00197     /*
00198      * One common requirement is to read values from the kernel.
00199      * This is usually initialised here, to speed up access when the
00200      *  information is read in, as a response to an incoming request.
00201      *
00202      * This module doesn't actually use this mechanism,
00203      * so this call is commented out here.
00204      */
00205     /*
00206      * auto_nlist( "example_symbol", 0, 0 ); 
00207      */
00208 }
00209 
00210         /*********************
00211          *
00212          *  Configuration file handling functions
00213          *
00214          *********************/
00215 
00216 void
00217 example_parse_config_exampleint(const char *token, char *cptr)
00218 {
00219     example_int = atoi(cptr);
00220 }
00221 
00222 void
00223 example_parse_config_examplestr(const char *token, char *cptr)
00224 {
00225     /*
00226      * Make sure the string fits in the space allocated for it.
00227      */
00228     if (strlen(cptr) < EXAMPLE_STR_LEN)
00229         strcpy(example_str, cptr);
00230     else {
00231         /*
00232          * Truncate the string if necessary.
00233          * An alternative approach would be to log an error,
00234          *  and discard this value altogether.
00235          */
00236         strncpy(example_str, cptr, EXAMPLE_STR_LEN - 4);
00237         example_str[EXAMPLE_STR_LEN - 4] = 0;
00238         strcat(example_str, "...");
00239         example_str[EXAMPLE_STR_LEN - 1] = 0;
00240     }
00241 }
00242 
00243         /*
00244          * We don't need to do anything special when closing down 
00245          */
00246 void
00247 example_free_config_exampleint(void)
00248 {
00249 }
00250 
00251 void
00252 example_free_config_examplestr(void)
00253 {
00254 }
00255 
00256         /*********************
00257          *
00258          *  System specific implementation functions
00259          *
00260          *********************/
00261 
00262     /*
00263      * Define the callback function used in the example_variables structure.
00264      * This is called whenever an incoming request refers to an object
00265      *  within this sub-tree.
00266      *
00267      * Four of the parameters are used to pass information in.
00268      * These are:
00269      *    vp      The entry from the 'example_variables' array for the
00270      *             object being queried.
00271      *    name    The OID from the request.
00272      *    length  The length of this OID.
00273      *    exact   A flag to indicate whether this is an 'exact' request
00274      *             (GET/SET) or an 'inexact' one (GETNEXT/GETBULK).
00275      *
00276      * Four of the parameters are used to pass information back out.
00277      * These are:
00278      *    name     The OID being returned.
00279      *    length   The length of this OID.
00280      *    var_len  The length of the answer being returned.
00281      *    write_method   A pointer to the SET function for this object.
00282      *
00283      * Note that name & length serve a dual purpose in both roles.
00284      */
00285 
00286 u_char         *
00287 var_example(struct variable *vp,
00288             oid * name,
00289             size_t * length,
00290             int exact, size_t * var_len, WriteMethod ** write_method)
00291 {
00292     /*
00293      *  The result returned from this function needs to be a pointer to
00294      *    static data (so that it can be accessed from outside).
00295      *  Define suitable variables for any type of data we may return.
00296      */
00297     static char     string[EXAMPLE_STR_LEN];    /* for EXAMPLESTRING   */
00298     static oid      oid_ret[8]; /* for EXAMPLEOBJECTID */
00299     static long     long_ret;   /* for everything else */
00300 
00301     /*
00302      * Before returning an answer, we need to check that the request
00303      *  refers to a valid instance of this object.  The utility routine
00304      *  'header_generic' can be used to do this for scalar objects.
00305      *
00306      * This routine 'header_simple_table' does the same thing for "simple"
00307      *  tables. (See the AGENT.txt file for the definition of a simple table).
00308      *
00309      * Both these utility routines also set up default values for the
00310      *  return arguments (assuming the check succeeded).
00311      * The name and length are set suitably for the current object,
00312      *  var_len assumes that the result is an integer of some form,
00313      *  and write_method assumes that the object cannot be set.
00314      *
00315      * If these assumptions are correct, this callback routine simply
00316      * needs to return a pointer to the appropriate value (using 'long_ret').
00317      * Otherwise, 'var_len' and/or 'write_method' should be set suitably.
00318      */
00319     DEBUGMSGTL(("example", "var_example entered\n"));
00320     if (header_generic(vp, name, length, exact, var_len, write_method) ==
00321         MATCH_FAILED)
00322         return NULL;
00323 
00324 
00325     /*
00326      * Many object will need to obtain data from the operating system in
00327      *  order to return the appropriate value.  Typically, this is done
00328      *  here - immediately following the 'header' call, and before the
00329      *  switch statement. This is particularly appropriate if a single 
00330      *  interface call can return data for all the objects supported.
00331      *
00332      * This example module does not rely on external data, so no such
00333      *  calls are needed in this case.  
00334      */
00335 
00336     /*
00337      * Now use the magic number from the variable pointer 'vp' to
00338      *  select the particular object being queried.
00339      * In each case, one of the static objects is set up with the
00340      *  appropriate information, and returned mapped to a 'u_char *'
00341      */
00342     switch (vp->magic) {
00343     case EXAMPLESTRING:
00344         sprintf(string, example_str);
00345         /*
00346          * Note that the assumption that the answer will be an
00347          *  integer does not hold true in this case, so the length
00348          *  of the answer needs to be set explicitly.           
00349          */
00350         *var_len = strlen(string);
00351         return (u_char *) string;
00352 
00353     case EXAMPLEINTEGER:
00354         /*
00355          * Here the length assumption is correct, but the
00356          *  object is writeable, so we need to set the
00357          *  write_method pointer as well as the current value.
00358          */
00359         long_ret = example_int;
00360         *write_method = write_exampleint;
00361         return (u_char *) & long_ret;
00362 
00363     case EXAMPLEOBJECTID:
00364         oid_ret[0] = 1;
00365         oid_ret[1] = 3;
00366         oid_ret[2] = 6;
00367         oid_ret[3] = 1;
00368         oid_ret[4] = 4;
00369         oid_ret[5] = oid_ret[6] = oid_ret[7] = 42;
00370         /*
00371          * Again, the assumption regarding the answer length is wrong.
00372          */
00373         *var_len = 8 * sizeof(oid);
00374         return (u_char *) oid_ret;
00375 
00376     case EXAMPLETIMETICKS:
00377         /*
00378          * Here both assumptions are correct,
00379          *  so we just need to set up the answer.
00380          */
00381         long_ret = 363136200;   /* 42 days, 42 minutes and 42.0 seconds */
00382         return (u_char *) & long_ret;
00383 
00384     case EXAMPLEIPADDRESS:
00385         /*
00386          * ipaddresses get returned as a long.  ick 
00387          */
00388         /*
00389          * we're returning 127.0.0.1 
00390          */
00391         long_ret = ntohl(INADDR_LOOPBACK);
00392         return (u_char *) & long_ret;
00393 
00394     case EXAMPLECOUNTER:
00395         long_ret = 42;
00396         return (u_char *) & long_ret;
00397 
00398     case EXAMPLEGAUGE:
00399         long_ret = 42;          /* Do we detect a theme running through these answers? */
00400         return (u_char *) & long_ret;
00401 
00402     case EXAMPLETRIGGERTRAP:
00403         /*
00404          * This object is essentially "write-only".
00405          * It only exists to trigger the sending of a trap.
00406          * Reading it will always return 0.
00407          */
00408         long_ret = 0;
00409         *write_method = write_exampletrap;
00410         return (u_char *) & long_ret;
00411 
00412     case EXAMPLETRIGGERTRAP2:
00413         /*
00414          * This object is essentially "write-only".
00415          * It only exists to trigger the sending of a v2 trap.
00416          * Reading it will always return 0.
00417          */
00418         long_ret = 0;
00419         *write_method = write_exampletrap2;
00420         return (u_char *) & long_ret;
00421 
00422     default:
00423         /*
00424          *  This will only be triggered if there's a problem with
00425          *   the coding of the module.  SNMP requests that reference
00426          *   a non-existant OID will be directed elsewhere.
00427          *  If this branch is reached, log an error, so that
00428          *   the problem can be investigated.
00429          */
00430         DEBUGMSGTL(("snmpd", "unknown sub-id %d in examples/var_example\n",
00431                     vp->magic));
00432     }
00433     /*
00434      * If we fall through to here, fail by returning NULL.
00435      * This is essentially a continuation of the 'default' case above.
00436      */
00437     return NULL;
00438 }
00439 
00440         /*********************
00441          *
00442          *  Writeable object SET handling routines
00443          *
00444          *********************/
00445 int
00446 write_exampleint(int action,
00447                  u_char * var_val,
00448                  u_char var_val_type,
00449                  size_t var_val_len,
00450                  u_char * statP, oid * name, size_t name_len)
00451 {
00452     /*
00453      * Define an arbitrary maximum permissible value 
00454      */
00455 #define MAX_EXAMPLE_INT 100
00456     static long     intval;
00457     static long     old_intval;
00458 
00459     switch (action) {
00460     case RESERVE1:
00461         /*
00462          *  Check that the value being set is acceptable
00463          */
00464         if (var_val_type != ASN_INTEGER) {
00465             DEBUGMSGTL(("example", "%x not integer type", var_val_type));
00466             return SNMP_ERR_WRONGTYPE;
00467         }
00468         if (var_val_len > sizeof(long)) {
00469             DEBUGMSGTL(("example", "wrong length %x", var_val_len));
00470             return SNMP_ERR_WRONGLENGTH;
00471         }
00472 
00473         intval = *((long *) var_val);
00474         if (intval > MAX_EXAMPLE_INT) {
00475             DEBUGMSGTL(("example", "wrong value %x", intval));
00476             return SNMP_ERR_WRONGVALUE;
00477         }
00478         break;
00479 
00480     case RESERVE2:
00481         /*
00482          *  This is conventially where any necesary
00483          *   resources are allocated (e.g. calls to malloc)
00484          *  Here, we are using static variables
00485          *   so don't need to worry about this.
00486          */
00487         break;
00488 
00489     case FREE:
00490         /*
00491          *  This is where any of the above resources
00492          *   are freed again (because one of the other
00493          *   values being SET failed for some reason).
00494          *  Again, since we are using static variables
00495          *   we don't need to worry about this either.
00496          */
00497         break;
00498 
00499     case ACTION:
00500         /*
00501          *  Set the variable as requested.
00502          *   Note that this may need to be reversed,
00503          *   so save any information needed to do this.
00504          */
00505         old_intval = example_int;
00506         example_int = intval;
00507         break;
00508 
00509     case UNDO:
00510         /*
00511          *  Something failed, so re-set the
00512          *   variable to its previous value
00513          *  (and free any allocated resources).
00514          */
00515         example_int = old_intval;
00516         break;
00517 
00518     case COMMIT:
00519         /*
00520          *  Everything worked, so we can discard any
00521          *   saved information, and make the change
00522          *   permanent (e.g. write to the config file).
00523          *  We also free any allocated resources.
00524          *
00525          *  In this case, there's nothing to do.
00526          */
00527         break;
00528 
00529     }
00530     return SNMP_ERR_NOERROR;
00531 }
00532 
00533 int
00534 write_exampletrap(int action,
00535                   u_char * var_val,
00536                   u_char var_val_type,
00537                   size_t var_val_len,
00538                   u_char * statP, oid * name, size_t name_len)
00539 {
00540     long            intval;
00541 
00542     DEBUGMSGTL(("example", "write_exampletrap entered: action=%d\n",
00543                 action));
00544     switch (action) {
00545     case RESERVE1:
00546         /*
00547          *  The only acceptable value is the integer 1
00548          */
00549         if (var_val_type != ASN_INTEGER) {
00550             DEBUGMSGTL(("example", "%x not integer type", var_val_type));
00551             return SNMP_ERR_WRONGTYPE;
00552         }
00553         if (var_val_len > sizeof(long)) {
00554             DEBUGMSGTL(("example", "wrong length %x", var_val_len));
00555             return SNMP_ERR_WRONGLENGTH;
00556         }
00557 
00558         intval = *((long *) var_val);
00559         if (intval != 1) {
00560             DEBUGMSGTL(("example", "wrong value %x", intval));
00561             return SNMP_ERR_WRONGVALUE;
00562         }
00563         break;
00564 
00565     case RESERVE2:
00566         /*
00567          * No resources are required.... 
00568          */
00569         break;
00570 
00571     case FREE:
00572         /*
00573          * ... so no resources need be freed 
00574          */
00575         break;
00576 
00577     case ACTION:
00578         /*
00579          *  Having triggered the sending of a trap,
00580          *   it would be impossible to revoke this,
00581          *   so we can't actually invoke the action here.
00582          */
00583         break;
00584 
00585     case UNDO:
00586         /*
00587          * We haven't done anything yet,
00588          * so there's nothing to undo 
00589          */
00590         break;
00591 
00592     case COMMIT:
00593         /*
00594          *  Everything else worked, so it's now safe
00595          *   to trigger the trap.
00596          *  Note that this is *only* acceptable since
00597          *   the trap sending routines are "failsafe".
00598          *  (In fact, they can fail, but they return no
00599          *   indication of this, which is the next best thing!)
00600          */
00601         DEBUGMSGTL(("example", "write_exampletrap sending the trap\n"));
00602         send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 99);
00603         DEBUGMSGTL(("example", "write_exampletrap trap sent\n"));
00604         break;
00605 
00606     }
00607     return SNMP_ERR_NOERROR;
00608 }
00609 
00610 /*
00611  * this documents how to send a SNMPv2 (and higher) trap via the
00612  * send_v2trap() API.
00613  * 
00614  * Coding SNMP-v2 Trap:
00615  * 
00616  * The SNMPv2-Trap PDU contains at least a pair of object names and
00617  * values: - sysUpTime.0 whose value is the time in hundredths of a
00618  * second since the netwok management portion of system was last
00619  * reinitialized.  - snmpTrapOID.0 which is part of the trap group SNMPv2
00620  * MIB whose value is the object-id of the specific trap you have defined
00621  * in your own MIB.  Other variables can be added to caracterize the
00622  * trap.
00623  * 
00624  * The function send_v2trap adds automaticallys the two objects but the
00625  * value of snmpTrapOID.0 is 0.0 by default. If you want to add your trap
00626  * name, you have to reconstruct this object and to add your own
00627  * variable.
00628  * 
00629  */
00630 
00631 
00632 
00633 int
00634 write_exampletrap2(int action,
00635                    u_char * var_val,
00636                    u_char var_val_type,
00637                    size_t var_val_len,
00638                    u_char * statP, oid * name, size_t name_len)
00639 {
00640     long            intval;
00641 
00642     /*
00643      * these variales will be used when we send the trap 
00644      */
00645     oid             objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };     /* snmpTrapOID.0 */
00646     oid             demo_trap[] = { 1, 3, 6, 1, 4, 1, 2021, 13, 990 };  /*demo-trap */
00647     oid             example_string_oid[] =
00648         { 1, 3, 6, 1, 4, 1, 2021, 254, 1, 0 };
00649     static netsnmp_variable_list var_trap;
00650     static netsnmp_variable_list var_obj;
00651 
00652     DEBUGMSGTL(("example", "write_exampletrap2 entered: action=%d\n",
00653                 action));
00654     switch (action) {
00655     case RESERVE1:
00656         /*
00657          *  The only acceptable value is the integer 1
00658          */
00659         if (var_val_type != ASN_INTEGER) {
00660             DEBUGMSGTL(("example", "%x not integer type", var_val_type));
00661             return SNMP_ERR_WRONGTYPE;
00662         }
00663         if (var_val_len > sizeof(long)) {
00664             DEBUGMSGTL(("example", "wrong length %x", var_val_len));
00665             return SNMP_ERR_WRONGLENGTH;
00666         }
00667 
00668         intval = *((long *) var_val);
00669         if (intval != 1) {
00670             DEBUGMSGTL(("example", "wrong value %x", intval));
00671             return SNMP_ERR_WRONGVALUE;
00672         }
00673         break;
00674 
00675     case RESERVE2:
00676         /*
00677          * No resources are required.... 
00678          */
00679         break;
00680 
00681     case FREE:
00682         /*
00683          * ... so no resources need be freed 
00684          */
00685         break;
00686 
00687     case ACTION:
00688         /*
00689          *  Having triggered the sending of a trap,
00690          *   it would be impossible to revoke this,
00691          *   so we can't actually invoke the action here.
00692          */
00693         break;
00694 
00695     case UNDO:
00696         /*
00697          * We haven't done anything yet,
00698          * so there's nothing to undo 
00699          */
00700         break;
00701 
00702     case COMMIT:
00703         /*
00704          *  Everything else worked, so it's now safe
00705          *   to trigger the trap.
00706          *  Note that this is *only* acceptable since
00707          *   the trap sending routines are "failsafe".
00708          *  (In fact, they can fail, but they return no
00709          *   indication of this, which is the next best thing!)
00710          */
00711 
00712         /*
00713          * trap definition objects 
00714          */
00715 
00716         var_trap.next_variable = &var_obj;      /* next variable */
00717         var_trap.name = objid_snmptrap; /* snmpTrapOID.0 */
00718         var_trap.name_length = sizeof(objid_snmptrap) / sizeof(oid);    /* number of sub-ids */
00719         var_trap.type = ASN_OBJECT_ID;
00720         var_trap.val.objid = demo_trap; /* demo-trap objid */
00721         var_trap.val_len = sizeof(demo_trap);   /* length in bytes (not number of subids!) */
00722 
00723 
00724         /*
00725          * additional objects 
00726          */
00727 
00728 
00729         var_obj.next_variable = NULL;   /* No more variables after this one */
00730         var_obj.name = example_string_oid;
00731         var_obj.name_length = sizeof(example_string_oid) / sizeof(oid); /* number of sub-ids */
00732         var_obj.type = ASN_OCTET_STR;   /* type of variable */
00733         var_obj.val.string = example_str;       /* value */
00734         var_obj.val_len = strlen(example_str);
00735         DEBUGMSGTL(("example", "write_exampletrap2 sending the v2 trap\n"));
00736         send_v2trap(&var_trap);
00737         DEBUGMSGTL(("example", "write_exampletrap2 v2 trap sent\n"));
00738 
00739         break;
00740 
00741     }
00742     return SNMP_ERR_NOERROR;
00743 }

net-snmpに対してSat Sep 5 13:14:21 2009に生成されました。  doxygen 1.4.7