net-snmp  5.4.1
watcher.c
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 }