net-snmp 5.7
|
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 #ifndef NETSNMP_NO_WRITE_SUPPORT 00176 case MODE_SET_RESERVE1: 00177 /* 00178 * check type 00179 */ 00180 if (requests->requestvb->type != ASN_INTEGER) { 00181 /* 00182 * not an integer. Bad dog, no bone. 00183 */ 00184 netsnmp_set_request_error(reqinfo, requests, 00185 SNMP_ERR_WRONGTYPE); 00186 /* 00187 * we don't need the cache any longer 00188 */ 00189 netsnmp_free_delegated_cache(cache); 00190 return; 00191 } 00192 break; 00193 00194 case MODE_SET_RESERVE2: 00195 /* 00196 * store old value for UNDO support in the future. 00197 */ 00198 memdup((u_char **) & delay_time_cache, 00199 (u_char *) & delay_time, sizeof(delay_time)); 00200 00201 /* 00202 * malloc failed 00203 */ 00204 if (delay_time_cache == NULL) { 00205 netsnmp_set_request_error(reqinfo, requests, 00206 SNMP_ERR_RESOURCEUNAVAILABLE); 00207 netsnmp_free_delegated_cache(cache); 00208 return; 00209 } 00210 00211 /* 00212 * Add our temporary information to the request itself. 00213 * This is then retrivable later. The free function 00214 * passed auto-frees it when the request is later 00215 * deleted. 00216 */ 00217 netsnmp_request_add_list_data(requests, 00218 netsnmp_create_data_list 00219 (DELAYED_INSTANCE_SET_NAME, 00220 delay_time_cache, free)); 00221 break; 00222 00223 case MODE_SET_ACTION: 00224 /* 00225 * update current value 00226 */ 00227 delay_time = *(requests->requestvb->val.integer); 00228 DEBUGMSGTL(("testhandler", "updated delay_time -> %ld\n", 00229 delay_time)); 00230 break; 00231 00232 case MODE_SET_UNDO: 00233 /* 00234 * ack, something somewhere failed. We reset back to the 00235 * previously old value by extracting the previosuly 00236 * stored information back out of the request 00237 */ 00238 delay_time = 00239 *((u_long *) netsnmp_request_get_list_data(requests, 00240 DELAYED_INSTANCE_SET_NAME)); 00241 break; 00242 00243 case MODE_SET_COMMIT: 00244 case MODE_SET_FREE: 00245 /* 00246 * the only thing to do here is free the old memdup'ed 00247 * value, but it's auto-freed by the datalist recovery, so 00248 * we don't have anything to actually do here 00249 */ 00250 break; 00251 #endif /* NETSNMP_NO_WRITE_SUPPORT */ 00252 } 00253 00254 /* 00255 * free the information cache 00256 */ 00257 netsnmp_free_delegated_cache(cache); 00258 }