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