net-snmp
5.4.1
|
00001 #include <net-snmp/net-snmp-config.h> 00002 00003 #include <stdlib.h> 00004 #if HAVE_STRING_H 00005 #include <string.h> 00006 #else 00007 #include <strings.h> 00008 #endif 00009 00010 #include <net-snmp/net-snmp-includes.h> 00011 #include <net-snmp/agent/net-snmp-agent-includes.h> 00012 00013 #include <net-snmp/agent/watcher.h> 00014 #include <net-snmp/agent/instance.h> 00015 #include <net-snmp/agent/scalar.h> 00016 00022 netsnmp_mib_handler * 00023 netsnmp_get_watcher_handler(void) 00024 { 00025 netsnmp_mib_handler *ret = NULL; 00026 00027 ret = netsnmp_create_handler("watcher", 00028 netsnmp_watcher_helper_handler); 00029 if (ret) { 00030 ret->flags |= MIB_HANDLER_AUTO_NEXT; 00031 } 00032 return ret; 00033 } 00034 00035 netsnmp_watcher_info * 00036 netsnmp_create_watcher_info(void *data, size_t size, u_char type, int flags) 00037 { 00038 netsnmp_watcher_info *winfo = SNMP_MALLOC_TYPEDEF(netsnmp_watcher_info); 00039 00040 winfo->data = data; 00041 winfo->data_size = size; 00042 winfo->max_size = size; /* Probably wrong for non-fixed size data */ 00043 winfo->type = type; 00044 if (flags) 00045 winfo->flags = flags; 00046 else 00047 winfo->flags = WATCHER_FIXED_SIZE; 00048 00049 return winfo; 00050 } 00051 00052 int 00053 netsnmp_register_watched_instance(netsnmp_handler_registration *reginfo, 00054 netsnmp_watcher_info *watchinfo) 00055 { 00056 netsnmp_mib_handler *whandler; 00057 00058 whandler = netsnmp_get_watcher_handler(); 00059 whandler->myvoid = (void *)watchinfo; 00060 00061 netsnmp_inject_handler(reginfo, whandler); 00062 return netsnmp_register_instance(reginfo); 00063 } 00064 00065 int 00066 netsnmp_register_watched_scalar(netsnmp_handler_registration *reginfo, 00067 netsnmp_watcher_info *watchinfo) 00068 { 00069 netsnmp_mib_handler *whandler; 00070 00071 whandler = netsnmp_get_watcher_handler(); 00072 whandler->myvoid = (void *)watchinfo; 00073 00074 netsnmp_inject_handler(reginfo, whandler); 00075 return netsnmp_register_scalar(reginfo); 00076 } 00077 00078 00079 00080 int 00081 netsnmp_watcher_helper_handler(netsnmp_mib_handler *handler, 00082 netsnmp_handler_registration *reginfo, 00083 netsnmp_agent_request_info *reqinfo, 00084 netsnmp_request_info *requests) 00085 { 00086 netsnmp_watcher_info *winfo = (netsnmp_watcher_info *) handler->myvoid; 00087 u_char *old_data; 00088 int cmp; 00089 00090 DEBUGMSGTL(("helper:watcher", "Got request: %d\n", reqinfo->mode)); 00091 cmp = snmp_oid_compare(requests->requestvb->name, 00092 requests->requestvb->name_length, 00093 reginfo->rootoid, reginfo->rootoid_len); 00094 00095 DEBUGMSGTL(( "helper:watcher", " oid:", cmp)); 00096 DEBUGMSGOID(("helper:watcher", requests->requestvb->name, 00097 requests->requestvb->name_length)); 00098 DEBUGMSG(( "helper:watcher", "\n")); 00099 00100 00101 00102 switch (reqinfo->mode) { 00103 /* 00104 * data requests 00105 */ 00106 case MODE_GET: 00107 snmp_set_var_typed_value(requests->requestvb, 00108 winfo->type, 00109 winfo->data, 00110 winfo->data_size); 00111 break; 00112 00113 /* 00114 * SET requests. Should only get here if registered RWRITE 00115 */ 00116 case MODE_SET_RESERVE1: 00117 if (requests->requestvb->type != winfo->type) 00118 netsnmp_set_request_error(reqinfo, requests, 00119 SNMP_ERR_WRONGTYPE); 00120 00121 if (((winfo->flags & WATCHER_MAX_SIZE) && 00122 requests->requestvb->val_len > winfo->max_size) || 00123 ((winfo->flags & WATCHER_FIXED_SIZE) && 00124 requests->requestvb->val_len != winfo->data_size)) 00125 netsnmp_set_request_error(reqinfo, requests, 00126 SNMP_ERR_WRONGLENGTH); 00127 break; 00128 00129 case MODE_SET_RESERVE2: 00130 /* 00131 * store old info for undo later 00132 */ 00133 memdup(&old_data, (u_char *) winfo->data, winfo->data_size); 00134 if (old_data == NULL) { 00135 netsnmp_set_request_error(reqinfo, requests, 00136 SNMP_ERR_RESOURCEUNAVAILABLE); 00137 return SNMP_ERR_NOERROR; 00138 } 00139 netsnmp_request_add_list_data(requests, 00140 netsnmp_create_data_list 00141 ("watcher", old_data, free)); 00142 break; 00143 00144 case MODE_SET_FREE: 00145 /* 00146 * nothing to do 00147 */ 00148 break; 00149 00150 case MODE_SET_ACTION: 00151 /* 00152 * update current 00153 */ 00154 memcpy(winfo->data, (void *)requests->requestvb->val.string, 00155 requests->requestvb->val_len); 00156 break; 00157 00158 case MODE_SET_UNDO: 00159 memcpy(winfo->data, 00160 netsnmp_request_get_list_data(requests, "watcher"), 00161 winfo->data_size); 00162 break; 00163 00164 case MODE_SET_COMMIT: 00165 winfo->data_size = requests->requestvb->val_len; 00166 break; 00167 00168 } 00169 00170 /* next handler called automatically - 'AUTO_NEXT' */ 00171 return SNMP_ERR_NOERROR; 00172 } 00173 00174 00175 /*************************** 00176 * 00177 * A specialised form of the above, reporting 00178 * the sysUpTime indicated by a given timestamp 00179 * 00180 ***************************/ 00181 00182 netsnmp_mib_handler * 00183 netsnmp_get_watched_timestamp_handler(void) 00184 { 00185 netsnmp_mib_handler *ret = NULL; 00186 00187 ret = netsnmp_create_handler("watcher", 00188 netsnmp_watched_timestamp_handler); 00189 if (ret) { 00190 ret->flags |= MIB_HANDLER_AUTO_NEXT; 00191 } 00192 return ret; 00193 } 00194 00195 int 00196 netsnmp_watched_timestamp_register(netsnmp_mib_handler *whandler, 00197 netsnmp_handler_registration *reginfo, 00198 marker_t timestamp) 00199 { 00200 whandler->myvoid = (void *)timestamp; 00201 netsnmp_inject_handler(reginfo, whandler); 00202 return netsnmp_register_scalar(reginfo); /* XXX - or instance? */ 00203 } 00204 00205 int 00206 netsnmp_register_watched_timestamp(netsnmp_handler_registration *reginfo, 00207 marker_t timestamp) 00208 { 00209 netsnmp_mib_handler *whandler; 00210 00211 whandler = netsnmp_get_watched_timestamp_handler(); 00212 00213 return netsnmp_watched_timestamp_register(whandler, reginfo, timestamp); 00214 } 00215 00216 00217 int 00218 netsnmp_watched_timestamp_handler(netsnmp_mib_handler *handler, 00219 netsnmp_handler_registration *reginfo, 00220 netsnmp_agent_request_info *reqinfo, 00221 netsnmp_request_info *requests) 00222 { 00223 marker_t timestamp = (marker_t) handler->myvoid; 00224 long uptime; 00225 int cmp; 00226 00227 DEBUGMSGTL(("helper:watcher:timestamp", 00228 "Got request: %d\n", reqinfo->mode)); 00229 cmp = snmp_oid_compare(requests->requestvb->name, 00230 requests->requestvb->name_length, 00231 reginfo->rootoid, reginfo->rootoid_len); 00232 00233 DEBUGMSGTL(( "helper:watcher:timestamp", " oid:", cmp)); 00234 DEBUGMSGOID(("helper:watcher:timestamp", requests->requestvb->name, 00235 requests->requestvb->name_length)); 00236 DEBUGMSG(( "helper:watcher:timestamp", "\n")); 00237 00238 00239 00240 switch (reqinfo->mode) { 00241 /* 00242 * data requests 00243 */ 00244 case MODE_GET: 00245 if (handler->flags & NETSNMP_WATCHER_DIRECT) 00246 uptime = * (long*)timestamp; 00247 else 00248 uptime = netsnmp_marker_uptime( timestamp ); 00249 snmp_set_var_typed_value(requests->requestvb, 00250 ASN_TIMETICKS, 00251 (u_char *) &uptime, 00252 sizeof(uptime)); 00253 break; 00254 00255 /* 00256 * Timestamps are inherently Read-Only, 00257 * so don't need to support SET requests. 00258 */ 00259 case MODE_SET_RESERVE1: 00260 netsnmp_set_request_error(reqinfo, requests, 00261 SNMP_ERR_NOTWRITABLE); 00262 return SNMP_ERR_NOTWRITABLE; 00263 } 00264 00265 /* next handler called automatically - 'AUTO_NEXT' */ 00266 return SNMP_ERR_NOERROR; 00267 } 00268 00269 /*************************** 00270 * 00271 * Another specialised form of the above, 00272 * implementing a 'TestAndIncr' spinlock 00273 * 00274 ***************************/ 00275 00276 netsnmp_mib_handler * 00277 netsnmp_get_watched_spinlock_handler(void) 00278 { 00279 netsnmp_mib_handler *ret = NULL; 00280 00281 ret = netsnmp_create_handler("watcher", 00282 netsnmp_watched_spinlock_handler); 00283 if (ret) { 00284 ret->flags |= MIB_HANDLER_AUTO_NEXT; 00285 } 00286 return ret; 00287 } 00288 00289 int 00290 netsnmp_register_watched_spinlock(netsnmp_handler_registration *reginfo, 00291 int *spinlock) 00292 { 00293 netsnmp_mib_handler *whandler; 00294 netsnmp_watcher_info *winfo; 00295 00296 whandler = netsnmp_get_watched_spinlock_handler(); 00297 whandler->myvoid = (void *)spinlock; 00298 winfo = netsnmp_create_watcher_info((void *)spinlock, 00299 sizeof(int), ASN_INTEGER, WATCHER_FIXED_SIZE); 00300 netsnmp_inject_handler(reginfo, whandler); 00301 return netsnmp_register_watched_scalar(reginfo, winfo); 00302 } 00303 00304 00305 int 00306 netsnmp_watched_spinlock_handler(netsnmp_mib_handler *handler, 00307 netsnmp_handler_registration *reginfo, 00308 netsnmp_agent_request_info *reqinfo, 00309 netsnmp_request_info *requests) 00310 { 00311 int *spinlock = (int *) handler->myvoid; 00312 netsnmp_request_info *request; 00313 int cmp; 00314 00315 DEBUGMSGTL(("helper:watcher:spinlock", 00316 "Got request: %d\n", reqinfo->mode)); 00317 cmp = snmp_oid_compare(requests->requestvb->name, 00318 requests->requestvb->name_length, 00319 reginfo->rootoid, reginfo->rootoid_len); 00320 00321 DEBUGMSGTL(( "helper:watcher:spinlock", " oid:", cmp)); 00322 DEBUGMSGOID(("helper:watcher:spinlock", requests->requestvb->name, 00323 requests->requestvb->name_length)); 00324 DEBUGMSG(( "helper:watcher:spinlock", "\n")); 00325 00326 00327 00328 switch (reqinfo->mode) { 00329 /* 00330 * Ensure the assigned value matches the current one 00331 */ 00332 case MODE_SET_RESERVE1: 00333 for (request=requests; request; request=request->next) { 00334 if (*request->requestvb->val.integer != *spinlock) { 00335 netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGVALUE); 00336 return SNMP_ERR_WRONGVALUE; 00337 00338 } 00339 } 00340 break; 00341 00342 /* 00343 * Everything else worked, so increment the spinlock 00344 */ 00345 case MODE_SET_COMMIT: 00346 (*spinlock)++; 00347 break; 00348 } 00349 00350 /* next handler called automatically - 'AUTO_NEXT' */ 00351 return SNMP_ERR_NOERROR; 00352 } 00353 00354 /*************************** 00355 * 00356 * Convenience registration routines - modelled on 00357 * the equivalent netsnmp_register_*_instance() calls 00358 * 00359 ***************************/ 00360 00361 int 00362 netsnmp_register_ulong_scalar(const char *name, 00363 oid * reg_oid, size_t reg_oid_len, 00364 u_long * it, 00365 Netsnmp_Node_Handler * subhandler) 00366 { 00367 return netsnmp_register_watched_scalar( 00368 netsnmp_create_handler_registration( 00369 name, subhandler, 00370 reg_oid, reg_oid_len, 00371 HANDLER_CAN_RWRITE ), 00372 netsnmp_create_watcher_info( 00373 (void *)it, sizeof( u_long ), 00374 ASN_UNSIGNED, WATCHER_FIXED_SIZE )); 00375 } 00376 00377 int 00378 netsnmp_register_read_only_ulong_scalar(const char *name, 00379 oid * reg_oid, size_t reg_oid_len, 00380 u_long * it, 00381 Netsnmp_Node_Handler * subhandler) 00382 { 00383 return netsnmp_register_watched_scalar( 00384 netsnmp_create_handler_registration( 00385 name, subhandler, 00386 reg_oid, reg_oid_len, 00387 HANDLER_CAN_RONLY ), 00388 netsnmp_create_watcher_info( 00389 (void *)it, sizeof( u_long ), 00390 ASN_UNSIGNED, WATCHER_FIXED_SIZE )); 00391 } 00392 00393 int 00394 netsnmp_register_long_scalar(const char *name, 00395 oid * reg_oid, size_t reg_oid_len, 00396 long * it, 00397 Netsnmp_Node_Handler * subhandler) 00398 { 00399 return netsnmp_register_watched_scalar( 00400 netsnmp_create_handler_registration( 00401 name, subhandler, 00402 reg_oid, reg_oid_len, 00403 HANDLER_CAN_RWRITE ), 00404 netsnmp_create_watcher_info( 00405 (void *)it, sizeof( long ), 00406 ASN_INTEGER, WATCHER_FIXED_SIZE )); 00407 } 00408 00409 int 00410 netsnmp_register_read_only_long_scalar(const char *name, 00411 oid * reg_oid, size_t reg_oid_len, 00412 long * it, 00413 Netsnmp_Node_Handler * subhandler) 00414 { 00415 return netsnmp_register_watched_scalar( 00416 netsnmp_create_handler_registration( 00417 name, subhandler, 00418 reg_oid, reg_oid_len, 00419 HANDLER_CAN_RONLY ), 00420 netsnmp_create_watcher_info( 00421 (void *)it, sizeof( long ), 00422 ASN_INTEGER, WATCHER_FIXED_SIZE )); 00423 } 00424 00425 00426 int 00427 netsnmp_register_int_scalar(const char *name, 00428 oid * reg_oid, size_t reg_oid_len, 00429 int * it, 00430 Netsnmp_Node_Handler * subhandler) 00431 { 00432 return netsnmp_register_watched_scalar( 00433 netsnmp_create_handler_registration( 00434 name, subhandler, 00435 reg_oid, reg_oid_len, 00436 HANDLER_CAN_RWRITE ), 00437 netsnmp_create_watcher_info( 00438 (void *)it, sizeof( int ), 00439 ASN_INTEGER, WATCHER_FIXED_SIZE )); 00440 } 00441 00442 int 00443 netsnmp_register_read_only_int_scalar(const char *name, 00444 oid * reg_oid, size_t reg_oid_len, 00445 int * it, 00446 Netsnmp_Node_Handler * subhandler) 00447 { 00448 return netsnmp_register_watched_scalar( 00449 netsnmp_create_handler_registration( 00450 name, subhandler, 00451 reg_oid, reg_oid_len, 00452 HANDLER_CAN_RONLY ), 00453 netsnmp_create_watcher_info( 00454 (void *)it, sizeof( int ), 00455 ASN_INTEGER, WATCHER_FIXED_SIZE )); 00456 } 00457 00458 00459 int 00460 netsnmp_register_read_only_counter32_scalar(const char *name, 00461 oid * reg_oid, size_t reg_oid_len, 00462 u_long * it, 00463 Netsnmp_Node_Handler * subhandler) 00464 { 00465 return netsnmp_register_watched_scalar( 00466 netsnmp_create_handler_registration( 00467 name, subhandler, 00468 reg_oid, reg_oid_len, 00469 HANDLER_CAN_RONLY ), 00470 netsnmp_create_watcher_info( 00471 (void *)it, sizeof( u_long ), 00472 ASN_COUNTER, WATCHER_FIXED_SIZE )); 00473 }