delayed_instance.c

00001 
00025 #include <net-snmp/net-snmp-config.h>
00026 #include <net-snmp/net-snmp-includes.h>
00027 #include <net-snmp/agent/net-snmp-agent-includes.h>
00028 
00029 #include "delayed_instance.h"
00030 
00031 static u_long   delay_time = 1;
00032 
00033 void
00034 init_delayed_instance(void)
00035 {
00036     static oid      my_delayed_oid[] =
00037         { 1, 3, 6, 1, 4, 1, 8072, 2, 1, 2, 0 };
00038     /*
00039      * delayed handler test
00040      */
00041     netsnmp_handler_registration *my_test;
00042 
00043     my_test =
00044         netsnmp_create_handler_registration("delayed_instance_example",
00045                                             delayed_instance_handler,
00046                                             my_delayed_oid,
00047                                             OID_LENGTH(my_delayed_oid),
00048                                             HANDLER_CAN_RWRITE);
00049 
00050     netsnmp_register_instance(my_test);
00051 }
00052 
00053 #define DELAYED_INSTANCE_SET_NAME "test_delayed"
00054 
00055 int
00056 delayed_instance_handler(netsnmp_mib_handler *handler,
00057                          netsnmp_handler_registration *reginfo,
00058                          netsnmp_agent_request_info *reqinfo,
00059                          netsnmp_request_info *requests)
00060 {
00061 
00062     DEBUGMSGTL(("delayed_instance", "Got request, mode = %d:\n",
00063                 reqinfo->mode));
00064 
00065     switch (reqinfo->mode) {
00066         /*
00067          * here we merely mention that we'll answer this request
00068          * later.  we don't actually care about the mode type in this
00069          * example, but for certain cases you may, so I'll leave in the
00070          * otherwise useless switch and case statements 
00071          */
00072 
00073     default:
00074         /*
00075          * mark this variable as something that can't be handled now.
00076          * We'll answer it later. 
00077          */
00078         requests->delegated = 1;
00079 
00080         /*
00081          * register an alarm to update the results at a later
00082          * time.  Normally, we might have to query something else
00083          * (like an external request sent to a different network
00084          * or system socket, etc), but for this example we'll do
00085          * something really simply and just insert an alarm for a
00086          * certain period of time 
00087          */
00088         snmp_alarm_register(delay_time, /* seconds */
00089                             0,  /* dont repeat. */
00090                             return_delayed_response,    /* the function
00091                                                          * to call */
00092                             /*
00093                              * here we create a "cache" of useful
00094                              * information that we'll want later
00095                              * on.  This argument is passed back
00096                              * to us in the callback function for
00097                              * an alarm 
00098                              */
00099                             (void *)
00100                             netsnmp_create_delegated_cache(handler,
00101                                                            reginfo,
00102                                                            reqinfo,
00103                                                            requests,
00104                                                            NULL));
00105         break;
00106 
00107     }
00108 
00109     return SNMP_ERR_NOERROR;
00110 }
00111 
00112 void
00113 return_delayed_response(unsigned int clientreg, void *clientarg)
00114 {
00115     /*
00116      * extract the cache from the passed argument 
00117      */
00118     netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *) clientarg;
00119 
00120     netsnmp_request_info *requests;
00121     netsnmp_agent_request_info *reqinfo;
00122     u_long         *delay_time_cache = NULL;
00123 
00124     /*
00125      * here we double check that the cache we created earlier is still
00126      * * valid.  If not, the request timed out for some reason and we
00127      * * don't need to keep processing things.  Should never happen, but
00128      * * this double checks. 
00129      */
00130     cache = netsnmp_handler_check_cache(cache);
00131 
00132     if (!cache) {
00133         snmp_log(LOG_ERR, "illegal call to return delayed response\n");
00134         return;
00135     }
00136 
00137     /*
00138      * re-establish the previous pointers we are used to having 
00139      */
00140     reqinfo = cache->reqinfo;
00141     requests = cache->requests;
00142 
00143     DEBUGMSGTL(("delayed_instance",
00144                 "continuing delayed request, mode = %d\n",
00145                 cache->reqinfo->mode));
00146 
00147     /*
00148      * mention that it's no longer delegated, and we've now answered
00149      * the query (which we'll do down below). 
00150      */
00151     requests->delegated = 0;
00152 
00153     switch (cache->reqinfo->mode) {
00154         /*
00155          * registering as an instance means we don't need to deal with
00156          * getnext processing, so we don't handle it here at all.
00157          * 
00158          * However, since the instance handler already reset the mode
00159          * back to GETNEXT from the faked GET mode, we need to do the
00160          * same thing in both cases.  This should be fixed in future
00161          * versions of net-snmp hopefully. 
00162          */
00163 
00164     case MODE_GET:
00165     case MODE_GETNEXT:
00166         /*
00167          * return the currend delay time 
00168          */
00169         snmp_set_var_typed_value(cache->requests->requestvb,
00170                                  ASN_INTEGER,
00171                                  (u_char *) & delay_time,
00172                                  sizeof(delay_time));
00173         break;
00174 
00175     case MODE_SET_RESERVE1:
00176         /*
00177          * check type 
00178          */
00179         if (requests->requestvb->type != ASN_INTEGER) {
00180             /*
00181              * not an integer.  Bad dog, no bone. 
00182              */
00183             netsnmp_set_request_error(reqinfo, requests,
00184                                       SNMP_ERR_WRONGTYPE);
00185             /*
00186              * we don't need the cache any longer 
00187              */
00188             netsnmp_free_delegated_cache(cache);
00189             return;
00190         }
00191         break;
00192 
00193     case MODE_SET_RESERVE2:
00194         /*
00195          * store old value for UNDO support in the future. 
00196          */
00197         memdup((u_char **) & delay_time_cache,
00198                (u_char *) & delay_time, sizeof(delay_time));
00199 
00200         /*
00201          * malloc failed 
00202          */
00203         if (delay_time_cache == NULL) {
00204             netsnmp_set_request_error(reqinfo, requests,
00205                                       SNMP_ERR_RESOURCEUNAVAILABLE);
00206             netsnmp_free_delegated_cache(cache);
00207             return;
00208         }
00209 
00210         /*
00211          * Add our temporary information to the request itself.
00212          * This is then retrivable later.  The free function
00213          * passed auto-frees it when the request is later
00214          * deleted.  
00215          */
00216         netsnmp_request_add_list_data(requests,
00217                                       netsnmp_create_data_list
00218                                       (DELAYED_INSTANCE_SET_NAME,
00219                                        delay_time_cache, free));
00220         break;
00221 
00222     case MODE_SET_ACTION:
00223         /*
00224          * update current value 
00225          */
00226         delay_time = *(requests->requestvb->val.integer);
00227         DEBUGMSGTL(("testhandler", "updated delay_time -> %d\n",
00228                     delay_time));
00229         break;
00230 
00231     case MODE_SET_UNDO:
00232         /*
00233          * ack, something somewhere failed.  We reset back to the
00234          * previously old value by extracting the previosuly
00235          * stored information back out of the request 
00236          */
00237         delay_time =
00238             *((u_long *) netsnmp_request_get_list_data(requests,
00239                                                        DELAYED_INSTANCE_SET_NAME));
00240         break;
00241 
00242     case MODE_SET_COMMIT:
00243     case MODE_SET_FREE:
00244         /*
00245          * the only thing to do here is free the old memdup'ed
00246          * value, but it's auto-freed by the datalist recovery, so
00247          * we don't have anything to actually do here 
00248          */
00249         break;
00250     }
00251 
00252     /*
00253      * free the information cache 
00254      */
00255     netsnmp_free_delegated_cache(cache);
00256 }

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