net-snmp 5.7
watcher.c
00001 #include <net-snmp/net-snmp-config.h>
00002 #include <net-snmp/net-snmp-features.h>
00003 
00004 #include <net-snmp/net-snmp-includes.h>
00005 #include <net-snmp/agent/net-snmp-agent-includes.h>
00006 
00007 #include <net-snmp/agent/watcher.h>
00008 
00009 #include <net-snmp/agent/instance.h>
00010 #include <net-snmp/agent/scalar.h>
00011 
00012 #include <string.h>
00013 
00014 #ifdef HAVE_DMALLOC_H
00015 static void free_wrapper(void * p)
00016 {
00017     free(p);
00018 }
00019 #else
00020 #define free_wrapper free
00021 #endif
00022 
00023 netsnmp_feature_provide(watcher_all)
00024 netsnmp_feature_child_of(watcher_all, mib_helpers)
00025 netsnmp_feature_child_of(watcher_create_info6, watcher_all)
00026 netsnmp_feature_child_of(watcher_register_timestamp, watcher_all)
00027 netsnmp_feature_child_of(watcher_ulong_scalar, watcher_all)
00028 netsnmp_feature_child_of(watcher_read_only_ulong_scalar, watcher_all)
00029 netsnmp_feature_child_of(watcher_read_only_int_scalar, watcher_all)
00030 netsnmp_feature_child_of(watcher_long_scalar, watcher_all)
00031 netsnmp_feature_child_of(watcher_read_only_long_scalar, watcher_all)
00032 netsnmp_feature_child_of(watcher_int_scalar, watcher_all)
00033 netsnmp_feature_child_of(read_only_counter32_scalar, watcher_all)
00034 netsnmp_feature_child_of(watcher_spinlock, watcher_all)
00035 
00041 netsnmp_mib_handler *
00042 netsnmp_get_watcher_handler(void)
00043 {
00044     netsnmp_mib_handler *ret = NULL;
00045     
00046     ret = netsnmp_create_handler("watcher",
00047                                  netsnmp_watcher_helper_handler);
00048     if (ret) {
00049         ret->flags |= MIB_HANDLER_AUTO_NEXT;
00050     }
00051     return ret;
00052 }
00053 
00054 netsnmp_watcher_info *
00055 netsnmp_init_watcher_info6(netsnmp_watcher_info *winfo,
00056                            void *data, size_t size, u_char type,
00057                            int flags, size_t max_size, size_t* size_p)
00058 {
00059     winfo->data = data;
00060     winfo->data_size = size;
00061     winfo->max_size = max_size;
00062     winfo->type = type;
00063     winfo->flags = flags;
00064     winfo->data_size_p = size_p;
00065     return winfo;
00066 }
00067 
00068 #ifndef NETSNMP_FEATURE_REMOVE_WATCHER_CREATE_INFO6
00069 netsnmp_watcher_info *
00070 netsnmp_create_watcher_info6(void *data, size_t size, u_char type,
00071                              int flags, size_t max_size, size_t* size_p)
00072 {
00073     netsnmp_watcher_info *winfo = SNMP_MALLOC_TYPEDEF(netsnmp_watcher_info);
00074     if (winfo)
00075         netsnmp_init_watcher_info6(winfo, data, size, type, flags, max_size,
00076                                    size_p);
00077     return winfo;
00078 }
00079 #endif /* NETSNMP_FEATURE_REMOVE_WATCHER_CREATE_INFO6 */
00080 
00081 netsnmp_watcher_info *
00082 netsnmp_init_watcher_info(netsnmp_watcher_info *winfo,
00083                           void *data, size_t size, u_char type, int flags)
00084 {
00085   return netsnmp_init_watcher_info6(winfo, data, size,
00086                                     type, (flags ? flags : WATCHER_FIXED_SIZE),
00087                                     size,  /* Probably wrong for non-fixed
00088                                             * size data */
00089                                     NULL);
00090 }
00091 
00092 netsnmp_watcher_info *
00093 netsnmp_create_watcher_info(void *data, size_t size, u_char type, int flags)
00094 {
00095     netsnmp_watcher_info *winfo = SNMP_MALLOC_TYPEDEF(netsnmp_watcher_info);
00096     if (winfo)
00097         netsnmp_init_watcher_info(winfo, data, size, type, flags);
00098     return winfo;
00099 }
00100 
00106 int
00107 netsnmp_register_watched_instance(netsnmp_handler_registration *reginfo,
00108                                   netsnmp_watcher_info         *watchinfo)
00109 {
00110     netsnmp_mib_handler *whandler;
00111 
00112     whandler         = netsnmp_get_watcher_handler();
00113     whandler->myvoid = (void *)watchinfo;
00114 
00115     netsnmp_inject_handler(reginfo, whandler);
00116     return netsnmp_register_instance(reginfo);
00117 }
00118 
00124 int
00125 netsnmp_register_watched_instance2(netsnmp_handler_registration *reginfo,
00126                                    netsnmp_watcher_info         *watchinfo)
00127 {
00128     netsnmp_mib_handler *whandler;
00129 
00130     whandler         = netsnmp_get_watcher_handler();
00131     whandler->myvoid = (void *)watchinfo;
00132     netsnmp_owns_watcher_info(whandler);
00133 
00134     netsnmp_inject_handler(reginfo, whandler);
00135     return netsnmp_register_instance(reginfo);
00136 }
00137 
00143 int
00144 netsnmp_register_watched_scalar(netsnmp_handler_registration *reginfo,
00145                                   netsnmp_watcher_info         *watchinfo)
00146 {
00147     netsnmp_mib_handler *whandler;
00148 
00149     whandler         = netsnmp_get_watcher_handler();
00150     whandler->myvoid = (void *)watchinfo;
00151 
00152     netsnmp_inject_handler(reginfo, whandler);
00153     return netsnmp_register_scalar(reginfo);
00154 }
00155 
00161 int
00162 netsnmp_register_watched_scalar2(netsnmp_handler_registration *reginfo,
00163                                   netsnmp_watcher_info         *watchinfo)
00164 {
00165     netsnmp_mib_handler *whandler;
00166 
00167     whandler         = netsnmp_get_watcher_handler();
00168     whandler->myvoid = (void *)watchinfo;
00169     netsnmp_owns_watcher_info(whandler);
00170 
00171     netsnmp_inject_handler(reginfo, whandler);
00172     return netsnmp_register_scalar(reginfo);
00173 }
00174 
00175 void
00176 netsnmp_owns_watcher_info(netsnmp_mib_handler *handler)
00177 {
00178     netsnmp_assert(handler);
00179     netsnmp_assert(handler->myvoid);
00180     handler->data_clone = (void *(*)(void *))netsnmp_clone_watcher_info;
00181     handler->data_free = free;
00182 }
00183 
00186 NETSNMP_STATIC_INLINE size_t
00187 get_data_size(const netsnmp_watcher_info* winfo)
00188 {
00189     if (winfo->flags & WATCHER_SIZE_STRLEN)
00190         return strlen((const char*)winfo->data);
00191     else {
00192         size_t res;
00193         if (winfo->flags & WATCHER_SIZE_IS_PTR)
00194             res = *winfo->data_size_p;
00195         else
00196             res = winfo->data_size;
00197         if (winfo->flags & WATCHER_SIZE_UNIT_OIDS)
00198           res *= sizeof(oid);
00199         return res;
00200     }
00201 }
00202 
00203 NETSNMP_STATIC_INLINE void
00204 set_data(netsnmp_watcher_info* winfo, void* data, size_t size)
00205 {
00206     memcpy(winfo->data, data, size);
00207     if (winfo->flags & WATCHER_SIZE_STRLEN)
00208         ((char*)winfo->data)[size] = '\0';
00209     else {
00210         if (winfo->flags & WATCHER_SIZE_UNIT_OIDS)
00211           size /= sizeof(oid);
00212         if (winfo->flags & WATCHER_SIZE_IS_PTR)
00213             *winfo->data_size_p = size;
00214         else
00215             winfo->data_size = size;
00216     }
00217 }
00218 
00219 typedef struct {
00220     size_t size;
00221     char data[1];
00222 } netsnmp_watcher_cache;
00223 
00224 NETSNMP_STATIC_INLINE netsnmp_watcher_cache*
00225 netsnmp_watcher_cache_create(const void* data, size_t size)
00226 {
00227     netsnmp_watcher_cache *res = (netsnmp_watcher_cache*)
00228         malloc(sizeof(netsnmp_watcher_cache) + size - 1);
00229     if (res) {
00230         res->size = size;
00231         memcpy(res->data, data, size);
00232     }
00233     return res;
00234 }
00235 
00238 int
00239 netsnmp_watcher_helper_handler(netsnmp_mib_handler *handler,
00240                                netsnmp_handler_registration *reginfo,
00241                                netsnmp_agent_request_info *reqinfo,
00242                                netsnmp_request_info *requests)
00243 {
00244     netsnmp_watcher_info  *winfo = (netsnmp_watcher_info *) handler->myvoid;
00245     netsnmp_watcher_cache *old_data;
00246 
00247     DEBUGMSGTL(("helper:watcher", "Got request:  %d\n", reqinfo->mode));
00248 
00249     DEBUGMSGTL(( "helper:watcher", "  oid:"));
00250     DEBUGMSGOID(("helper:watcher", requests->requestvb->name,
00251                                    requests->requestvb->name_length));
00252     DEBUGMSG((   "helper:watcher", "\n"));
00253 
00254 
00255 
00256     switch (reqinfo->mode) {
00257         /*
00258          * data requests 
00259          */
00260     case MODE_GET:
00261         snmp_set_var_typed_value(requests->requestvb,
00262                                  winfo->type,
00263                                  winfo->data,
00264                                  get_data_size(winfo));
00265         break;
00266 
00267         /*
00268          * SET requests.  Should only get here if registered RWRITE 
00269          */
00270 #ifndef NETSNMP_NO_WRITE_SUPPORT
00271     case MODE_SET_RESERVE1:
00272         if (requests->requestvb->type != winfo->type) {
00273             netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGTYPE);
00274             handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
00275         } else if (((winfo->flags & WATCHER_MAX_SIZE) &&
00276                      requests->requestvb->val_len > winfo->max_size) ||
00277             ((winfo->flags & WATCHER_FIXED_SIZE) &&
00278                 requests->requestvb->val_len != get_data_size(winfo))) {
00279             netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGLENGTH);
00280             handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
00281         } else if ((winfo->flags & WATCHER_SIZE_STRLEN) &&
00282             (memchr(requests->requestvb->val.string, '\0',
00283                 requests->requestvb->val_len) != NULL)) {
00284             netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGVALUE);
00285             handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
00286         }
00287         break;
00288 
00289     case MODE_SET_RESERVE2:
00290         /*
00291          * store old info for undo later 
00292          */
00293         old_data =
00294             netsnmp_watcher_cache_create(winfo->data, get_data_size(winfo));
00295         if (old_data == NULL) {
00296             netsnmp_set_request_error(reqinfo, requests,
00297                                       SNMP_ERR_RESOURCEUNAVAILABLE);
00298             handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
00299         } else
00300             netsnmp_request_add_list_data(requests,
00301                                           netsnmp_create_data_list
00302                                           ("watcher", old_data, &free_wrapper));
00303         break;
00304 
00305     case MODE_SET_FREE:
00306         /*
00307          * nothing to do 
00308          */
00309         break;
00310 
00311     case MODE_SET_ACTION:
00312         /*
00313          * update current 
00314          */
00315         set_data(winfo, (void *)requests->requestvb->val.string,
00316                                 requests->requestvb->val_len);
00317         break;
00318 
00319     case MODE_SET_UNDO:
00320         old_data = (netsnmp_watcher_cache*)netsnmp_request_get_list_data(requests, "watcher");
00321         set_data(winfo, old_data->data, old_data->size);
00322         break;
00323 
00324     case MODE_SET_COMMIT:
00325         break;
00326 #endif /* NETSNMP_NO_WRITE_SUPPORT */
00327 
00328     default:
00329         snmp_log(LOG_ERR, "watcher handler called with an unknown mode: %d\n",
00330                  reqinfo->mode);
00331         return SNMP_ERR_GENERR;
00332 
00333     }
00334 
00335     /* next handler called automatically - 'AUTO_NEXT' */
00336     return SNMP_ERR_NOERROR;
00337 }
00338 
00339 
00340     /***************************
00341      *
00342      * A specialised form of the above, reporting
00343      *   the sysUpTime indicated by a given timestamp
00344      *
00345      ***************************/
00346 
00347 netsnmp_mib_handler *
00348 netsnmp_get_watched_timestamp_handler(void)
00349 {
00350     netsnmp_mib_handler *ret = NULL;
00351     
00352     ret = netsnmp_create_handler("watcher-timestamp",
00353                                  netsnmp_watched_timestamp_handler);
00354     if (ret) {
00355         ret->flags |= MIB_HANDLER_AUTO_NEXT;
00356     }
00357     return ret;
00358 }
00359 
00360 int
00361 netsnmp_watched_timestamp_register(netsnmp_mib_handler *whandler,
00362                                    netsnmp_handler_registration *reginfo,
00363                                    marker_t timestamp)
00364 {
00365     whandler->myvoid = (void *)timestamp;
00366     netsnmp_inject_handler(reginfo, whandler);
00367     return netsnmp_register_scalar(reginfo);   /* XXX - or instance? */
00368 }
00369 
00370 #ifndef NETSNMP_FEATURE_REMOVE_WATCHER_REGISTER_TIMESTAMP
00371 int
00372 netsnmp_register_watched_timestamp(netsnmp_handler_registration *reginfo,
00373                                    marker_t timestamp)
00374 {
00375     netsnmp_mib_handler *whandler;
00376 
00377     whandler         = netsnmp_get_watched_timestamp_handler();
00378 
00379     return netsnmp_watched_timestamp_register(whandler, reginfo, timestamp);
00380 }
00381 #endif /* NETSNMP_FEATURE_REMOVE_WATCHER_REGISTER_TIMESTAMP */
00382 
00383 
00384 int
00385 netsnmp_watched_timestamp_handler(netsnmp_mib_handler *handler,
00386                                netsnmp_handler_registration *reginfo,
00387                                netsnmp_agent_request_info *reqinfo,
00388                                netsnmp_request_info *requests)
00389 {
00390     marker_t timestamp = (marker_t) handler->myvoid;
00391     long     uptime;
00392 
00393     DEBUGMSGTL(("helper:watcher:timestamp",
00394                                "Got request:  %d\n", reqinfo->mode));
00395 
00396     DEBUGMSGTL(( "helper:watcher:timestamp", "  oid:"));
00397     DEBUGMSGOID(("helper:watcher:timestamp", requests->requestvb->name,
00398                                    requests->requestvb->name_length));
00399     DEBUGMSG((   "helper:watcher:timestamp", "\n"));
00400 
00401 
00402 
00403     switch (reqinfo->mode) {
00404         /*
00405          * data requests 
00406          */
00407     case MODE_GET:
00408         if (handler->flags & NETSNMP_WATCHER_DIRECT)
00409             uptime = * (long*)timestamp;
00410         else
00411             uptime = netsnmp_marker_uptime( timestamp );
00412         snmp_set_var_typed_value(requests->requestvb,
00413                                  ASN_TIMETICKS,
00414                                  (u_char *) &uptime,
00415                                  sizeof(uptime));
00416         break;
00417 
00418         /*
00419          * Timestamps are inherently Read-Only,
00420          *  so don't need to support SET requests.
00421          */
00422 #ifndef NETSNMP_NO_WRITE_SUPPORT
00423     case MODE_SET_RESERVE1:
00424         netsnmp_set_request_error(reqinfo, requests,
00425                                   SNMP_ERR_NOTWRITABLE);
00426         handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
00427         return SNMP_ERR_NOTWRITABLE;
00428 #endif /* NETSNMP_NO_WRITE_SUPPORT */
00429     }
00430 
00431     /* next handler called automatically - 'AUTO_NEXT' */
00432     return SNMP_ERR_NOERROR;
00433 }
00434 
00435     /***************************
00436      *
00437      * Another specialised form of the above,
00438      *   implementing a 'TestAndIncr' spinlock
00439      *
00440      ***************************/
00441 
00442 #ifndef NETSNMP_FEATURE_REMOVE_WATCHER_SPINLOCK
00443 
00444 netsnmp_mib_handler *
00445 netsnmp_get_watched_spinlock_handler(void)
00446 {
00447     netsnmp_mib_handler *ret = NULL;
00448     
00449     ret = netsnmp_create_handler("watcher-spinlock",
00450                                  netsnmp_watched_spinlock_handler);
00451     if (ret) {
00452         ret->flags |= MIB_HANDLER_AUTO_NEXT;
00453     }
00454     return ret;
00455 }
00456 
00457 int
00458 netsnmp_register_watched_spinlock(netsnmp_handler_registration *reginfo,
00459                                    int *spinlock)
00460 {
00461     netsnmp_mib_handler  *whandler;
00462     netsnmp_watcher_info *winfo;
00463 
00464     whandler         = netsnmp_get_watched_spinlock_handler();
00465     whandler->myvoid = (void *)spinlock;
00466     winfo            = netsnmp_create_watcher_info((void *)spinlock,
00467                            sizeof(int), ASN_INTEGER, WATCHER_FIXED_SIZE);
00468     netsnmp_inject_handler(reginfo, whandler);
00469     return netsnmp_register_watched_scalar2(reginfo, winfo);
00470 }
00471 
00472 
00473 int
00474 netsnmp_watched_spinlock_handler(netsnmp_mib_handler *handler,
00475                                netsnmp_handler_registration *reginfo,
00476                                netsnmp_agent_request_info *reqinfo,
00477                                netsnmp_request_info *requests)
00478 {
00479     int     *spinlock = (int *) handler->myvoid;
00480     netsnmp_request_info *request;
00481 
00482     DEBUGMSGTL(("helper:watcher:spinlock",
00483                                "Got request:  %d\n", reqinfo->mode));
00484 
00485     DEBUGMSGTL(( "helper:watcher:spinlock", "  oid:"));
00486     DEBUGMSGOID(("helper:watcher:spinlock", requests->requestvb->name,
00487                                    requests->requestvb->name_length));
00488     DEBUGMSG((   "helper:watcher:spinlock", "\n"));
00489 
00490 
00491 
00492     switch (reqinfo->mode) {
00493         /*
00494          * Ensure the assigned value matches the current one
00495          */
00496 #ifndef NETSNMP_NO_WRITE_SUPPORT
00497     case MODE_SET_RESERVE1:
00498         for (request=requests; request; request=request->next) {
00499             if (request->processed)
00500                 continue;
00501 
00502             if (*request->requestvb->val.integer != *spinlock) {
00503                 netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGVALUE);
00504                 handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
00505                 return SNMP_ERR_WRONGVALUE;
00506 
00507             }
00508         }
00509         break;
00510 
00511         /*
00512          * Everything else worked, so increment the spinlock
00513          */
00514     case MODE_SET_COMMIT:
00515         (*spinlock)++;
00516         break;
00517 #endif /* NETSNMP_NO_WRITE_SUPPORT */
00518     }
00519 
00520     /* next handler called automatically - 'AUTO_NEXT' */
00521     return SNMP_ERR_NOERROR;
00522 }
00523 #endif /* NETSNMP_FEATURE_REMOVE_WATCHER_SPINLOCK */
00524 
00525     /***************************
00526      *
00527      *   Convenience registration routines - modelled on
00528      *   the equivalent netsnmp_register_*_instance() calls
00529      *
00530      ***************************/
00531 
00532 netsnmp_watcher_info *
00533 netsnmp_clone_watcher_info(netsnmp_watcher_info *winfo)
00534 {
00535     netsnmp_watcher_info *copy = malloc(sizeof(*copy));
00536     if (copy)
00537         *copy = *winfo;
00538     return copy;
00539 }
00540 
00541 static int
00542 register_scalar_watcher(const char* name,
00543                         const oid* reg_oid, size_t reg_oid_len,
00544                         void *data, size_t size, u_char type,
00545                         Netsnmp_Node_Handler * subhandler, int mode)
00546 {
00547     netsnmp_handler_registration *reginfo = NULL;
00548     netsnmp_mib_handler *whandler = NULL;
00549     netsnmp_watcher_info* watchinfo =
00550         netsnmp_create_watcher_info(data, size, type, WATCHER_FIXED_SIZE);
00551     if (watchinfo)
00552         whandler = netsnmp_get_watcher_handler();
00553     if (watchinfo && whandler) {
00554         whandler->myvoid = watchinfo;
00555         netsnmp_owns_watcher_info(whandler);
00556         reginfo =
00557             netsnmp_create_handler_registration(
00558                 name, subhandler, reg_oid, reg_oid_len, mode);
00559     }
00560     if (watchinfo && whandler && reginfo) {
00561         netsnmp_inject_handler(reginfo, whandler);
00562         return netsnmp_register_scalar(reginfo);
00563     }
00564     if (whandler)
00565         netsnmp_handler_free(whandler);
00566     else if (watchinfo)
00567         free(watchinfo);
00568     return SNMP_ERR_RESOURCEUNAVAILABLE;
00569 }
00570 
00571 #ifndef NETSNMP_FEATURE_REMOVE_WATCHER_ULONG_SCALAR
00572 int
00573 netsnmp_register_ulong_scalar(const char *name,
00574                               const oid * reg_oid, size_t reg_oid_len,
00575                               u_long * it,
00576                               Netsnmp_Node_Handler * subhandler)
00577 {
00578     return register_scalar_watcher(
00579         name, reg_oid, reg_oid_len,
00580         (void *)it, sizeof( u_long ),
00581         ASN_UNSIGNED, subhandler, HANDLER_CAN_RWRITE);
00582 }
00583 #endif /* NETSNMP_FEATURE_REMOVE_WATCHER_ULONG_SCALAR */
00584 
00585 #ifndef NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_ULONG_SCALAR
00586 int
00587 netsnmp_register_read_only_ulong_scalar(const char *name,
00588                               const oid * reg_oid, size_t reg_oid_len,
00589                               u_long * it,
00590                               Netsnmp_Node_Handler * subhandler)
00591 {
00592     return register_scalar_watcher(
00593         name, reg_oid, reg_oid_len,
00594         (void *)it, sizeof( u_long ),
00595         ASN_UNSIGNED, subhandler, HANDLER_CAN_RONLY);
00596 }
00597 #endif /* NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_ULONG_SCALAR */
00598 
00599 #ifndef NETSNMP_FEATURE_REMOVE_WATCHER_LONG_SCALAR
00600 int
00601 netsnmp_register_long_scalar(const char *name,
00602                               const oid * reg_oid, size_t reg_oid_len,
00603                               long * it,
00604                               Netsnmp_Node_Handler * subhandler)
00605 {
00606     return register_scalar_watcher(
00607         name, reg_oid, reg_oid_len,
00608         (void *)it, sizeof( long ),
00609         ASN_INTEGER, subhandler, HANDLER_CAN_RWRITE);
00610 }
00611 #endif /* NETSNMP_FEATURE_REMOVE_WATCHER_LONG_SCALAR */
00612 
00613 #ifndef NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_LONG_SCALAR
00614 int
00615 netsnmp_register_read_only_long_scalar(const char *name,
00616                               const oid * reg_oid, size_t reg_oid_len,
00617                               long * it,
00618                               Netsnmp_Node_Handler * subhandler)
00619 {
00620     return register_scalar_watcher(
00621         name, reg_oid, reg_oid_len,
00622         (void *)it, sizeof( long ),
00623         ASN_INTEGER, subhandler, HANDLER_CAN_RONLY);
00624 }
00625 #endif /* NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_LONG_SCALAR */
00626 
00627 
00628 #ifndef NETSNMP_FEATURE_REMOVE_WATCHER_INT_SCALAR
00629 int
00630 netsnmp_register_int_scalar(const char *name,
00631                               const oid * reg_oid, size_t reg_oid_len,
00632                               int * it,
00633                               Netsnmp_Node_Handler * subhandler)
00634 {
00635     return register_scalar_watcher(
00636         name, reg_oid, reg_oid_len,
00637         (void *)it, sizeof( int ),
00638         ASN_INTEGER, subhandler, HANDLER_CAN_RWRITE);
00639 }
00640 #endif /* NETSNMP_FEATURE_REMOVE_WATCHER_INT_SCALAR */
00641 
00642 #ifndef NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_INT_SCALAR
00643 int
00644 netsnmp_register_read_only_int_scalar(const char *name,
00645                               const oid * reg_oid, size_t reg_oid_len,
00646                               int * it,
00647                               Netsnmp_Node_Handler * subhandler)
00648 {
00649     return register_scalar_watcher(
00650         name, reg_oid, reg_oid_len,
00651         (void *)it, sizeof( int ),
00652         ASN_INTEGER, subhandler, HANDLER_CAN_RONLY);
00653 }
00654 #endif /* NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_INT_SCALAR */
00655 
00656 #ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_COUNTER32_SCALAR
00657 int
00658 netsnmp_register_read_only_counter32_scalar(const char *name,
00659                               const oid * reg_oid, size_t reg_oid_len,
00660                               u_long * it,
00661                               Netsnmp_Node_Handler * subhandler)
00662 {
00663     return register_scalar_watcher(
00664         name, reg_oid, reg_oid_len,
00665         (void *)it, sizeof( u_long ),
00666         ASN_COUNTER, subhandler, HANDLER_CAN_RONLY);
00667 }
00668 #endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_COUNTER32_SCALAR */
00669