net-snmp 5.7
instance.c
00001 /* Portions of this file are subject to the following copyright(s).  See
00002  * the Net-SNMP's COPYING file for more details and other copyrights
00003  * that may apply:
00004  */
00005 /*
00006  * Portions of this file are copyrighted by:
00007  * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
00008  * Use is subject to license terms specified in the COPYING file
00009  * distributed with the Net-SNMP package.
00010  */
00011 #include <net-snmp/net-snmp-config.h>
00012 #include <net-snmp/net-snmp-features.h>
00013 
00014 #include <net-snmp/net-snmp-includes.h>
00015 #include <net-snmp/agent/net-snmp-agent-includes.h>
00016 
00017 #include <net-snmp/agent/instance.h>
00018 
00019 #include <stdlib.h>
00020 #if HAVE_STRING_H
00021 #include <string.h>
00022 #else
00023 #include <strings.h>
00024 #endif
00025 
00026 #include <net-snmp/net-snmp-includes.h>
00027 #include <net-snmp/agent/serialize.h>
00028 #include <net-snmp/agent/read_only.h>
00029 
00030 netsnmp_feature_provide(instance)
00031 netsnmp_feature_child_of(instance, mib_helpers)
00032 
00033 typedef struct netsnmp_num_file_instance_s {
00034     int   refcnt;
00035     char *file_name;
00036     FILE *filep;
00037     u_char type;
00038     int   flags;
00039 } netsnmp_num_file_instance;
00040 
00047 static netsnmp_num_file_instance *
00048 netsnmp_num_file_instance_ref(netsnmp_num_file_instance *nfi)
00049 {
00050     nfi->refcnt++;
00051     return nfi;
00052 }
00053 
00054 static void
00055 netsnmp_num_file_instance_deref(netsnmp_num_file_instance *nfi)
00056 {
00057     if (--nfi->refcnt == 0) {
00058         free(nfi->file_name);
00059         free(nfi);
00060     }
00061 }
00062 
00070 netsnmp_mib_handler *
00071 netsnmp_get_instance_handler(void)
00072 {
00073     return netsnmp_create_handler("instance",
00074                                   netsnmp_instance_helper_handler);
00075 }
00076 
00095 int
00096 netsnmp_register_instance(netsnmp_handler_registration *reginfo)
00097 {
00098     netsnmp_mib_handler *handler = netsnmp_get_instance_handler();
00099     handler->flags |= MIB_HANDLER_INSTANCE;
00100     netsnmp_inject_handler(reginfo, handler);
00101     return netsnmp_register_serialize(reginfo);
00102 }
00103 
00122 int
00123 netsnmp_register_read_only_instance(netsnmp_handler_registration *reginfo)
00124 {
00125     netsnmp_inject_handler(reginfo, netsnmp_get_instance_handler());
00126     netsnmp_inject_handler(reginfo, netsnmp_get_read_only_handler());
00127     return netsnmp_register_serialize(reginfo);
00128 }
00129 
00130 static
00131 netsnmp_handler_registration *
00132 get_reg(const char *name,
00133         const char *ourname,
00134         const oid * reg_oid, size_t reg_oid_len,
00135         netsnmp_num_file_instance *it,
00136         int modes,
00137         Netsnmp_Node_Handler * scalarh, Netsnmp_Node_Handler * subhandler,
00138         const char *contextName)
00139 {
00140     netsnmp_handler_registration *myreg;
00141     netsnmp_mib_handler *myhandler;
00142 
00143     if (subhandler) {
00144         myreg =
00145             netsnmp_create_handler_registration(name,
00146                                                 subhandler,
00147                                                 reg_oid, reg_oid_len,
00148                                                 modes);
00149         myhandler = netsnmp_create_handler(ourname, scalarh);
00150         myhandler->myvoid = it;
00151         myhandler->data_clone = (void*(*)(void*))netsnmp_num_file_instance_ref;
00152         myhandler->data_free = (void(*)(void*))netsnmp_num_file_instance_deref;
00153         netsnmp_inject_handler(myreg, myhandler);
00154     } else {
00155         myreg =
00156             netsnmp_create_handler_registration(name,
00157                                                 scalarh,
00158                                                 reg_oid, reg_oid_len,
00159                                                 modes);
00160         myreg->handler->myvoid = it;
00161         myreg->handler->data_clone
00162             = (void *(*)(void *))netsnmp_num_file_instance_ref;
00163         myreg->handler->data_free
00164             = (void (*)(void *))netsnmp_num_file_instance_deref;
00165     }
00166     if (contextName)
00167         myreg->contextName = strdup(contextName);
00168     return myreg;
00169 }
00170 
00171 /* Watched 'long' instances are writable on both 32-bit and 64-bit systems  */
00172 netsnmp_feature_child_of(read_only_ulong_instance,instance)
00173 #ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_ULONG_INSTANCE
00174 int
00175 netsnmp_register_read_only_ulong_instance(const char *name,
00176                                           const oid * reg_oid,
00177                                           size_t reg_oid_len, u_long * it,
00178                                           Netsnmp_Node_Handler *
00179                                           subhandler)
00180 {
00181     return netsnmp_register_watched_instance2(
00182                netsnmp_create_handler_registration(
00183                    name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY),
00184                netsnmp_create_watcher_info(
00185                    (void *)it, sizeof(u_long),
00186                    ASN_UNSIGNED, WATCHER_FIXED_SIZE));
00187 }
00188 #endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_ULONG_INSTANCE */
00189 
00190 netsnmp_feature_child_of(ulong_instance,instance)
00191 #ifndef NETSNMP_FEATURE_REMOVE_ULONG_INSTANCE
00192 int
00193 netsnmp_register_ulong_instance(const char *name,
00194                                 const oid * reg_oid, size_t reg_oid_len,
00195                                 u_long * it,
00196                                 Netsnmp_Node_Handler * subhandler)
00197 {
00198     return netsnmp_register_watched_instance2(
00199                netsnmp_create_handler_registration(
00200                    name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE),
00201                netsnmp_create_watcher_info(
00202                    (void *)it, sizeof(u_long),
00203                    ASN_UNSIGNED, WATCHER_FIXED_SIZE));
00204 }
00205 #endif /* NETSNMP_FEATURE_REMOVE_ULONG_INSTANCE */
00206 
00207 netsnmp_feature_child_of(read_only_counter32_instance,instance)
00208 #ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_COUNTER32_INSTANCE
00209 int
00210 netsnmp_register_read_only_counter32_instance(const char *name,
00211                                               const oid * reg_oid,
00212                                               size_t reg_oid_len,
00213                                               u_long * it,
00214                                               Netsnmp_Node_Handler *
00215                                               subhandler)
00216 {
00217     return netsnmp_register_watched_instance2(
00218                netsnmp_create_handler_registration(
00219                    name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY),
00220                netsnmp_create_watcher_info(
00221                    (void *)it, sizeof(u_long),
00222                    ASN_COUNTER, WATCHER_FIXED_SIZE));
00223 }
00224 #endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_COUNTER32_INSTANCE */
00225 
00226 netsnmp_feature_child_of(read_only_long_instance,instance)
00227 #ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_LONG_INSTANCE
00228 int
00229 netsnmp_register_read_only_long_instance(const char *name,
00230                                          const oid * reg_oid,
00231                                          size_t reg_oid_len,
00232                                          long *it,
00233                                          Netsnmp_Node_Handler * subhandler)
00234 {
00235     return netsnmp_register_watched_instance2(
00236                netsnmp_create_handler_registration(
00237                    name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY),
00238                netsnmp_create_watcher_info(
00239                    (void *)it, sizeof(long), ASN_INTEGER, WATCHER_FIXED_SIZE));
00240 }
00241 #endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_LONG_INSTANCE */
00242 
00243 netsnmp_feature_child_of(long_instance,instance)
00244 #ifndef NETSNMP_FEATURE_REMOVE_LONG_INSTANCE
00245 int
00246 netsnmp_register_long_instance(const char *name,
00247                                const oid * reg_oid, size_t reg_oid_len,
00248                                long *it, Netsnmp_Node_Handler * subhandler)
00249 {
00250     return netsnmp_register_watched_instance2(
00251                netsnmp_create_handler_registration(
00252                    name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE),
00253                netsnmp_create_watcher_info(
00254                    (void *)it, sizeof(long), ASN_INTEGER, WATCHER_FIXED_SIZE));
00255 }
00256 #endif /* NETSNMP_FEATURE_REMOVE_LONG_INSTANCE */
00257 
00258 /* Watched 'int' instances are only writable on 32-bit systems  */
00259 netsnmp_feature_child_of(read_only_uint_instance,instance)
00260 #ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_UINT_INSTANCE
00261 int
00262 netsnmp_register_read_only_uint_instance(const char *name,
00263                                          const oid * reg_oid,
00264                                          size_t reg_oid_len,
00265                                          unsigned int *it,
00266                                          Netsnmp_Node_Handler * subhandler)
00267 {
00268     return netsnmp_register_watched_instance2(
00269                netsnmp_create_handler_registration(
00270                    name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY),
00271                netsnmp_create_watcher_info(
00272                    (void *)it, sizeof(unsigned int),
00273                    ASN_UNSIGNED, WATCHER_FIXED_SIZE));
00274 }
00275 #endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_UINT_INSTANCE */
00276 
00277 netsnmp_feature_child_of(uint_instance,instance)
00278 #ifndef NETSNMP_FEATURE_REMOVE_UINT_INSTANCE
00279 int
00280 netsnmp_register_uint_instance(const char *name,
00281                                const oid * reg_oid, size_t reg_oid_len,
00282                                unsigned int *it, Netsnmp_Node_Handler * subhandler)
00283 {
00284     return netsnmp_register_watched_instance2(
00285                netsnmp_create_handler_registration(
00286                    name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE),
00287                netsnmp_create_watcher_info(
00288                    (void *)it, sizeof(unsigned int),
00289                    ASN_UNSIGNED, WATCHER_FIXED_SIZE));
00290 }
00291 #endif /* NETSNMP_FEATURE_REMOVE_UINT_INSTANCE */
00292 
00293 netsnmp_feature_child_of(read_only_int_instance,instance)
00294 #ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_INT_INSTANCE
00295 int
00296 netsnmp_register_read_only_int_instance(const char *name,
00297                                 const oid * reg_oid, size_t reg_oid_len,
00298                                 int *it, Netsnmp_Node_Handler * subhandler)
00299 {
00300     return netsnmp_register_watched_instance2(
00301                netsnmp_create_handler_registration(
00302                    name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY),
00303                netsnmp_create_watcher_info(
00304                    (void *)it, sizeof(int), ASN_INTEGER, WATCHER_FIXED_SIZE));
00305 }
00306 #endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_INT_INSTANCE */
00307 
00308   /*
00309    * Compatibility with earlier (inconsistently named) routine
00310    */
00311 netsnmp_feature_child_of(register_read_only_int_instance,netsnmp_unused)
00312 #ifndef NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_INT_INSTANCE
00313 int
00314 register_read_only_int_instance(const char *name,
00315                                 const oid * reg_oid, size_t reg_oid_len,
00316                                 int *it, Netsnmp_Node_Handler * subhandler)
00317 {
00318   return netsnmp_register_read_only_int_instance(name,
00319                                 reg_oid, reg_oid_len,
00320                                 it, subhandler);
00321 }
00322 #endif /* NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_INT_INSTANCE */
00323 
00324 /*
00325  * Context registrations
00326  */
00327 
00328 netsnmp_feature_child_of(register_read_only_ulong_instance_context,instance)
00329 #ifndef NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_ULONG_INSTANCE_CONTEXT
00330 int
00331 netsnmp_register_read_only_ulong_instance_context(const char *name,
00332                                                   const oid * reg_oid,
00333                                                   size_t reg_oid_len,
00334                                                   u_long * it,
00335                                                   Netsnmp_Node_Handler *
00336                                                   subhandler,
00337                                                   const char *contextName)
00338 {
00339     netsnmp_handler_registration *myreg =
00340       netsnmp_create_handler_registration(
00341           name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY);
00342     if (myreg && contextName)
00343       myreg->contextName = strdup(contextName);
00344     return netsnmp_register_watched_instance2(
00345         myreg, netsnmp_create_watcher_info(
00346             (void *)it, sizeof(u_long), ASN_UNSIGNED, WATCHER_FIXED_SIZE));
00347 }
00348 #endif /* NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_ULONG_INSTANCE_CONTEXT */
00349 
00350 netsnmp_feature_child_of(register_ulong_instance_context,instance)
00351 #ifndef NETSNMP_FEATURE_REMOVE_REGISTER_ULONG_INSTANCE_CONTEXT
00352 int
00353 netsnmp_register_ulong_instance_context(const char *name,
00354                                         const oid * reg_oid, size_t reg_oid_len,
00355                                         u_long * it,
00356                                         Netsnmp_Node_Handler * subhandler,
00357                                         const char *contextName)
00358 {
00359     netsnmp_handler_registration *myreg =
00360       netsnmp_create_handler_registration(
00361           name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE);
00362     if (myreg && contextName)
00363       myreg->contextName = strdup(contextName);
00364     return netsnmp_register_watched_instance2(
00365         myreg, netsnmp_create_watcher_info(
00366             (void *)it, sizeof(u_long), ASN_UNSIGNED, WATCHER_FIXED_SIZE));
00367 }
00368 #endif /* NETSNMP_FEATURE_REMOVE_REGISTER_ULONG_INSTANCE_CONTEXT */
00369 
00370 netsnmp_feature_child_of(register_read_only_counter32_instance_context,instance)
00371 #ifndef NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_COUNTER32_INSTANCE_CONTEXT
00372 int
00373 netsnmp_register_read_only_counter32_instance_context(const char *name,
00374                                                       const oid * reg_oid,
00375                                                       size_t reg_oid_len,
00376                                                       u_long * it,
00377                                                       Netsnmp_Node_Handler *
00378                                                       subhandler,
00379                                                       const char *contextName)
00380 {
00381     netsnmp_handler_registration *myreg =
00382       netsnmp_create_handler_registration(
00383           name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY);
00384     if (myreg && contextName)
00385       myreg->contextName = strdup(contextName);
00386     return netsnmp_register_watched_instance2(
00387         myreg, netsnmp_create_watcher_info(
00388             (void *)it, sizeof(u_long), ASN_COUNTER, WATCHER_FIXED_SIZE));
00389 }
00390 #endif /* NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_COUNTER32_INSTANCE_CONTEXT */
00391 
00392 netsnmp_feature_child_of(register_read_only_long_instance_context,instance)
00393 #ifndef NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_LONG_INSTANCE_CONTEXT
00394 int
00395 netsnmp_register_read_only_long_instance_context(const char *name,
00396                                                  const oid * reg_oid,
00397                                                  size_t reg_oid_len,
00398                                                  long *it,
00399                                                  Netsnmp_Node_Handler
00400                                                  *subhandler,
00401                                                  const char *contextName)
00402 {
00403     netsnmp_handler_registration *myreg =
00404       netsnmp_create_handler_registration(
00405           name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY);
00406     if (myreg && contextName)
00407       myreg->contextName = strdup(contextName);
00408     return netsnmp_register_watched_instance2(
00409         myreg, netsnmp_create_watcher_info(
00410             (void *)it, sizeof(long), ASN_INTEGER, WATCHER_FIXED_SIZE));
00411 }
00412 #endif /* NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_LONG_INSTANCE_CONTEXT */
00413 
00414 netsnmp_feature_child_of(register_long_instance_context,instance)
00415 #ifndef NETSNMP_FEATURE_REMOVE_REGISTER_LONG_INSTANCE_CONTEXT
00416 int
00417 netsnmp_register_long_instance_context(const char *name,
00418                                        const oid * reg_oid, size_t reg_oid_len,
00419                                        long *it,
00420                                        Netsnmp_Node_Handler * subhandler,
00421                                        const char *contextName)
00422 {
00423     netsnmp_handler_registration *myreg =
00424       netsnmp_create_handler_registration(
00425           name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE);
00426     if (myreg && contextName)
00427       myreg->contextName = strdup(contextName);
00428     return netsnmp_register_watched_instance2(
00429         myreg, netsnmp_create_watcher_info(
00430             (void *)it, sizeof(long), ASN_INTEGER, WATCHER_FIXED_SIZE));
00431 }
00432 #endif /* NETSNMP_FEATURE_REMOVE_REGISTER_LONG_INSTANCE_CONTEXT */
00433 
00434 netsnmp_feature_child_of(register_int_instance_context,instance)
00435 #ifndef NETSNMP_FEATURE_REMOVE_REGISTER_INT_INSTANCE_CONTEXT
00436 int
00437 netsnmp_register_int_instance_context(const char *name,
00438                                       const oid * reg_oid,
00439                                       size_t reg_oid_len,
00440                                       int *it,
00441                                       Netsnmp_Node_Handler * subhandler,
00442                                       const char *contextName)
00443 {
00444     netsnmp_handler_registration *myreg =
00445       netsnmp_create_handler_registration(
00446           name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE);
00447     if (myreg && contextName)
00448       myreg->contextName = strdup(contextName);
00449     return netsnmp_register_watched_instance2(
00450         myreg, netsnmp_create_watcher_info(
00451             (void *)it, sizeof(int), ASN_INTEGER, WATCHER_FIXED_SIZE));
00452 }
00453 #endif /* NETSNMP_FEATURE_REMOVE_REGISTER_INT_INSTANCE_CONTEXT */
00454 
00455 netsnmp_feature_child_of(register_read_only_int_instance_context,instance)
00456 #ifndef NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_INT_INSTANCE_CONTEXT
00457 int
00458 netsnmp_register_read_only_int_instance_context(const char *name,
00459                                                 const oid * reg_oid,
00460                                                 size_t reg_oid_len,
00461                                                 int *it,
00462                                                 Netsnmp_Node_Handler * subhandler,
00463                                                 const char *contextName)
00464 {
00465     netsnmp_handler_registration *myreg =
00466       netsnmp_create_handler_registration(
00467           name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY);
00468     if (myreg && contextName)
00469       myreg->contextName = strdup(contextName);
00470     return netsnmp_register_watched_instance2(
00471         myreg, netsnmp_create_watcher_info(
00472             (void *)it, sizeof(int), ASN_INTEGER, WATCHER_FIXED_SIZE));
00473 }
00474 #endif /* NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_INT_INSTANCE_CONTEXT */
00475 
00476 /*
00477  * Compatibility with earlier (inconsistently named) routine
00478  */
00479 netsnmp_feature_child_of(read_only_int_instance_context,instance)
00480 #ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_INT_INSTANCE_CONTEXT
00481 int
00482 register_read_only_int_instance_context(const char *name,
00483                                         const oid * reg_oid, size_t reg_oid_len,
00484                                         int *it,
00485                                         Netsnmp_Node_Handler * subhandler,
00486                                         const char *contextName)
00487 {
00488     return netsnmp_register_read_only_int_instance_context(name,
00489                                                            reg_oid, reg_oid_len,
00490                                                            it, subhandler,
00491                                                            contextName);
00492 }
00493 #endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_INT_INSTANCE_CONTEXT */
00494 
00495 netsnmp_feature_child_of(register_num_file_instance,instance)
00496 #ifndef NETSNMP_FEATURE_REMOVE_REGISTER_NUM_FILE_INSTANCE
00497 int
00498 netsnmp_register_num_file_instance(const char *name,
00499                                    const oid * reg_oid, size_t reg_oid_len,
00500                                    const char *file_name, int asn_type, int mode,
00501                                    Netsnmp_Node_Handler * subhandler,
00502                                    const char *contextName)
00503 {
00504     netsnmp_handler_registration *myreg;
00505     netsnmp_num_file_instance *nfi;
00506 
00507     if ((NULL == name) || (NULL == reg_oid) || (NULL == file_name)) {
00508         snmp_log(LOG_ERR, "bad parameter to netsnmp_register_num_file_instance\n");
00509         return MIB_REGISTRATION_FAILED;
00510     }
00511 
00512     nfi = SNMP_MALLOC_TYPEDEF(netsnmp_num_file_instance);
00513     if ((NULL == nfi) ||
00514         (NULL == (nfi->file_name = strdup(file_name)))) {
00515         snmp_log(LOG_ERR, "could not not allocate memory\n");
00516         if (NULL != nfi)
00517             free(nfi); /* SNMP_FREE overkill on local var */
00518         return MIB_REGISTRATION_FAILED;
00519     }
00520 
00521     nfi->refcnt = 1;
00522     myreg = get_reg(name, "file_num_handler", reg_oid, reg_oid_len, nfi,
00523                     mode, netsnmp_instance_num_file_handler,
00524                     subhandler, contextName);
00525     if (NULL == myreg) {
00526         netsnmp_num_file_instance_deref(nfi);
00527         return MIB_REGISTRATION_FAILED;
00528     }
00529 
00530     nfi->type = asn_type;
00531 
00532     if (HANDLER_CAN_RONLY == mode)
00533         return netsnmp_register_read_only_instance(myreg);
00534 
00535     return netsnmp_register_instance(myreg);
00536 }
00537 #endif /* NETSNMP_FEATURE_REMOVE_REGISTER_NUM_FILE_INSTANCE */
00538 
00557 netsnmp_feature_child_of(register_int_instance,instance)
00558 #ifndef NETSNMP_FEATURE_REMOVE_REGISTER_INT_INSTANCE
00559 int
00560 netsnmp_register_int_instance(const char *name,
00561                               const oid * reg_oid, size_t reg_oid_len,
00562                               int *it, Netsnmp_Node_Handler * subhandler)
00563 {
00564     return netsnmp_register_watched_instance2(
00565                netsnmp_create_handler_registration(
00566                    name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE),
00567                netsnmp_create_watcher_info(
00568                    (void *)it, sizeof(int), ASN_INTEGER, WATCHER_FIXED_SIZE));
00569 }
00570 #endif /* NETSNMP_FEATURE_REMOVE_REGISTER_INT_INSTANCE */
00571 
00572 #ifdef HAVE_DMALLOC_H
00573 static void free_wrapper(void * p)
00574 {
00575     free(p);
00576 }
00577 #else
00578 #define free_wrapper free
00579 #endif
00580 
00581 int
00582 netsnmp_instance_num_file_handler(netsnmp_mib_handler *handler,
00583                                   netsnmp_handler_registration *reginfo,
00584                                   netsnmp_agent_request_info *reqinfo,
00585                                   netsnmp_request_info *requests)
00586 {
00587     netsnmp_num_file_instance *nfi;
00588     u_long it;
00589 #ifndef NETSNMP_NO_WRITE_SUPPORT
00590     u_long *it_save;
00591 #endif /* NETSNMP_NO_WRITE_SUPPORT */
00592     int rc;
00593 
00594     netsnmp_assert(NULL != handler);
00595     nfi = (netsnmp_num_file_instance *)handler->myvoid;
00596     netsnmp_assert(NULL != nfi);
00597     netsnmp_assert(NULL != nfi->file_name);
00598 
00599     DEBUGMSGTL(("netsnmp_instance_int_handler", "Got request:  %d\n",
00600                 reqinfo->mode));
00601 
00602     switch (reqinfo->mode) {
00603         /*
00604          * data requests 
00605          */
00606     case MODE_GET:
00607         /*
00608          * Use a long here, otherwise on 64 bit use of an int would fail
00609          */
00610         netsnmp_assert(NULL == nfi->filep);
00611         nfi->filep = fopen(nfi->file_name, "r");
00612         if (NULL == nfi->filep) {
00613             netsnmp_set_request_error(reqinfo, requests,
00614                                       SNMP_NOSUCHINSTANCE);
00615             return SNMP_ERR_NOERROR;
00616         }
00617         rc = fscanf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
00618                     &it);
00619         fclose(nfi->filep);
00620         nfi->filep = NULL;
00621         if (rc != 1) {
00622             netsnmp_set_request_error(reqinfo, requests,
00623                                       SNMP_NOSUCHINSTANCE);
00624             return SNMP_ERR_NOERROR;
00625         }
00626         snmp_set_var_typed_value(requests->requestvb, nfi->type,
00627                                  (u_char *) &it, sizeof(it));
00628         break;
00629 
00630         /*
00631          * SET requests.  Should only get here if registered RWRITE 
00632          */
00633 #ifndef NETSNMP_NO_WRITE_SUPPORT
00634     case MODE_SET_RESERVE1:
00635         netsnmp_assert(NULL == nfi->filep);
00636         if (requests->requestvb->type != nfi->type)
00637             netsnmp_set_request_error(reqinfo, requests,
00638                                       SNMP_ERR_WRONGTYPE);
00639         break;
00640 
00641     case MODE_SET_RESERVE2:
00642         netsnmp_assert(NULL == nfi->filep);
00643         nfi->filep = fopen(nfi->file_name, "w+");
00644         if (NULL == nfi->filep) {
00645             netsnmp_set_request_error(reqinfo, requests,
00646                                       SNMP_ERR_NOTWRITABLE);
00647             return SNMP_ERR_NOERROR;
00648         }
00649         /*
00650          * store old info for undo later 
00651          */
00652         if (fscanf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
00653                    &it) != 1) {
00654             netsnmp_set_request_error(reqinfo, requests,
00655                                       SNMP_ERR_RESOURCEUNAVAILABLE);
00656             return SNMP_ERR_NOERROR;
00657         }
00658 
00659         memdup((u_char **) & it_save, (u_char *)&it, sizeof(u_long));
00660         if (it_save == NULL) {
00661             netsnmp_set_request_error(reqinfo, requests,
00662                                       SNMP_ERR_RESOURCEUNAVAILABLE);
00663             return SNMP_ERR_NOERROR;
00664         }
00665         netsnmp_request_add_list_data(requests,
00666                                       netsnmp_create_data_list
00667                                       (INSTANCE_HANDLER_NAME, it_save,
00668                                        &free_wrapper));
00669         break;
00670 
00671     case MODE_SET_ACTION:
00672         /*
00673          * update current 
00674          */
00675         DEBUGMSGTL(("helper:instance", "updated %s -> %ld\n", nfi->file_name,
00676                     *(requests->requestvb->val.integer)));
00677         it = *(requests->requestvb->val.integer);
00678         rewind(nfi->filep); /* rewind to make sure we are at the beginning */
00679         rc = fprintf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
00680                      it);
00681         if (rc < 0) {
00682             netsnmp_set_request_error(reqinfo, requests,
00683                                       SNMP_ERR_GENERR);
00684             return SNMP_ERR_NOERROR;
00685         }
00686         break;
00687 
00688     case MODE_SET_UNDO:
00689         it =
00690             *((u_int *) netsnmp_request_get_list_data(requests,
00691                                                       INSTANCE_HANDLER_NAME));
00692         rc = fprintf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
00693                      it);
00694         if (rc < 0)
00695             netsnmp_set_request_error(reqinfo, requests,
00696                                       SNMP_ERR_UNDOFAILED);
00699     case MODE_SET_COMMIT:
00700     case MODE_SET_FREE:
00701         if (NULL != nfi->filep) {
00702             fclose(nfi->filep);
00703             nfi->filep = NULL;
00704         }
00705         break;
00706 #endif /* NETSNMP_NO_WRITE_SUPPORT */
00707     default:
00708         snmp_log(LOG_ERR,
00709                  "netsnmp_instance_num_file_handler: illegal mode\n");
00710         netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR);
00711         return SNMP_ERR_NOERROR;
00712     }
00713 
00714     if (handler->next && handler->next->access_method)
00715         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00716                                          requests);
00717     return SNMP_ERR_NOERROR;
00718 }
00719 
00720 int
00721 netsnmp_instance_helper_handler(netsnmp_mib_handler *handler,
00722                                 netsnmp_handler_registration *reginfo,
00723                                 netsnmp_agent_request_info *reqinfo,
00724                                 netsnmp_request_info *requests)
00725 {
00726 
00727     netsnmp_variable_list *var = requests->requestvb;
00728 
00729     int             ret, cmp;
00730 
00731     DEBUGMSGTL(("helper:instance", "Got request:\n"));
00732     cmp = snmp_oid_compare(requests->requestvb->name,
00733                            requests->requestvb->name_length,
00734                            reginfo->rootoid, reginfo->rootoid_len);
00735 
00736     DEBUGMSGTL(("helper:instance", "  oid:"));
00737     DEBUGMSGOID(("helper:instance", var->name, var->name_length));
00738     DEBUGMSG(("helper:instance", "\n"));
00739 
00740     switch (reqinfo->mode) {
00741     case MODE_GET:
00742         if (cmp != 0) {
00743             netsnmp_set_request_error(reqinfo, requests,
00744                                       SNMP_NOSUCHINSTANCE);
00745             return SNMP_ERR_NOERROR;
00746         } else {
00747             return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00748                                              requests);
00749         }
00750         break;
00751 
00752 #ifndef NETSNMP_NO_WRITE_SUPPORT
00753     case MODE_SET_RESERVE1:
00754     case MODE_SET_RESERVE2:
00755     case MODE_SET_ACTION:
00756     case MODE_SET_COMMIT:
00757     case MODE_SET_UNDO:
00758     case MODE_SET_FREE:
00759         if (cmp != 0) {
00760             netsnmp_set_request_error(reqinfo, requests,
00761                                       SNMP_ERR_NOCREATION);
00762             return SNMP_ERR_NOERROR;
00763         } else {
00764             return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00765                                              requests);
00766         }
00767         break;
00768 #endif /* NETSNMP_NO_WRITE_SUPPORT */
00769 
00770     case MODE_GETNEXT:
00771         if (cmp < 0 || (cmp == 0 && requests->inclusive)) {
00772             reqinfo->mode = MODE_GET;
00773             snmp_set_var_objid(requests->requestvb, reginfo->rootoid,
00774                                reginfo->rootoid_len);
00775             ret =
00776                 netsnmp_call_next_handler(handler, reginfo, reqinfo,
00777                                           requests);
00778             reqinfo->mode = MODE_GETNEXT;
00779             /*
00780              * if the instance doesn't have data, set type to ASN_NULL
00781              * to move to the next sub-tree. Ignore delegated requests; they
00782              * might have data later on.
00783              */
00784             if (!requests->delegated &&
00785                 (requests->requestvb->type == SNMP_NOSUCHINSTANCE ||
00786                  requests->requestvb->type == SNMP_NOSUCHOBJECT)) {
00787                 requests->requestvb->type = ASN_NULL;
00788             }
00789             return ret;
00790         } else {
00791             return SNMP_ERR_NOERROR;
00792         }
00793         break;
00794     default:
00795         snmp_log(LOG_ERR,
00796                  "netsnmp_instance_helper_handler: illegal mode\n");
00797         netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR);
00798         return SNMP_ERR_NOERROR;
00799     }
00800     /*
00801      * got here only if illegal mode found 
00802      */
00803     return SNMP_ERR_GENERR;
00804 }
00805