net-snmp  5.4.1
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 
00013 #include <stdlib.h>
00014 #if HAVE_STRING_H
00015 #include <string.h>
00016 #else
00017 #include <strings.h>
00018 #endif
00019 
00020 #include <net-snmp/net-snmp-includes.h>
00021 #include <net-snmp/agent/net-snmp-agent-includes.h>
00022 
00023 #include <net-snmp/agent/instance.h>
00024 #include <net-snmp/agent/serialize.h>
00025 #include <net-snmp/agent/read_only.h>
00026 
00027 typedef struct netsnmp_num_file_instance_s {
00028     char *file_name;
00029     FILE *filep;
00030     int   type;
00031     int   flags;
00032 } netsnmp_num_file_instance;
00033 
00047 netsnmp_mib_handler *
00048 netsnmp_get_instance_handler(void)
00049 {
00050     return netsnmp_create_handler("instance",
00051                                   netsnmp_instance_helper_handler);
00052 }
00053 
00072 int
00073 netsnmp_register_instance(netsnmp_handler_registration *reginfo)
00074 {
00075     netsnmp_mib_handler *handler = netsnmp_get_instance_handler();
00076     handler->flags |= MIB_HANDLER_INSTANCE;
00077     netsnmp_inject_handler(reginfo, handler);
00078     return netsnmp_register_serialize(reginfo);
00079 }
00080 
00099 int
00100 netsnmp_register_read_only_instance(netsnmp_handler_registration *reginfo)
00101 {
00102     netsnmp_inject_handler(reginfo, netsnmp_get_instance_handler());
00103     netsnmp_inject_handler(reginfo, netsnmp_get_read_only_handler());
00104     return netsnmp_register_serialize(reginfo);
00105 }
00106 
00107 static
00108 netsnmp_handler_registration *
00109 get_reg(const char *name,
00110         const char *ourname,
00111         oid * reg_oid, size_t reg_oid_len,
00112         void *it,
00113         int modes,
00114         Netsnmp_Node_Handler * scalarh, Netsnmp_Node_Handler * subhandler,
00115         const char *contextName)
00116 {
00117     netsnmp_handler_registration *myreg;
00118     netsnmp_mib_handler *myhandler;
00119 
00120     if (subhandler) {
00121         myreg =
00122             netsnmp_create_handler_registration(name,
00123                                                 subhandler,
00124                                                 reg_oid, reg_oid_len,
00125                                                 modes);
00126         myhandler = netsnmp_create_handler(ourname, scalarh);
00127         myhandler->myvoid = (void *) it;
00128         netsnmp_inject_handler(myreg, myhandler);
00129     } else {
00130         myreg =
00131             netsnmp_create_handler_registration(name,
00132                                                 scalarh,
00133                                                 reg_oid, reg_oid_len,
00134                                                 modes);
00135         myreg->handler->myvoid = (void *) it;
00136     }
00137     if (contextName)
00138         myreg->contextName = strdup(contextName);
00139     return myreg;
00140 }
00141 
00142 int
00143 netsnmp_register_read_only_ulong_instance(const char *name,
00144                                           oid * reg_oid,
00145                                           size_t reg_oid_len, u_long * it,
00146                                           Netsnmp_Node_Handler *
00147                                           subhandler)
00148 {
00149     netsnmp_handler_registration *myreg;
00150 
00151     myreg = get_reg(name, "ulong_handler", reg_oid, reg_oid_len, it,
00152                     HANDLER_CAN_RONLY, netsnmp_instance_ulong_handler,
00153                     subhandler, NULL);
00154     return netsnmp_register_read_only_instance(myreg);
00155 }
00156 
00157 int
00158 netsnmp_register_ulong_instance(const char *name,
00159                                 oid * reg_oid, size_t reg_oid_len,
00160                                 u_long * it,
00161                                 Netsnmp_Node_Handler * subhandler)
00162 {
00163     netsnmp_handler_registration *myreg;
00164 
00165     myreg = get_reg(name, "ulong_handler", reg_oid, reg_oid_len, it,
00166                     HANDLER_CAN_RWRITE, netsnmp_instance_ulong_handler,
00167                     subhandler, NULL);
00168     return netsnmp_register_instance(myreg);
00169 }
00170 
00171 int
00172 netsnmp_register_read_only_counter32_instance(const char *name,
00173                                               oid * reg_oid,
00174                                               size_t reg_oid_len,
00175                                               u_long * it,
00176                                               Netsnmp_Node_Handler *
00177                                               subhandler)
00178 {
00179     netsnmp_handler_registration *myreg;
00180 
00181     myreg = get_reg(name, "counter32_handler", reg_oid, reg_oid_len, it,
00182                     HANDLER_CAN_RONLY, netsnmp_instance_counter32_handler,
00183                     subhandler, NULL);
00184     return netsnmp_register_read_only_instance(myreg);
00185 }
00186 
00187 int
00188 netsnmp_register_read_only_long_instance(const char *name,
00189                                          oid * reg_oid, size_t reg_oid_len,
00190                                          long *it,
00191                                          Netsnmp_Node_Handler * subhandler)
00192 {
00193     netsnmp_handler_registration *myreg;
00194 
00195     myreg = get_reg(name, "long_handler", reg_oid, reg_oid_len, it,
00196                     HANDLER_CAN_RONLY, netsnmp_instance_long_handler,
00197                     subhandler, NULL);
00198     return netsnmp_register_read_only_instance(myreg);
00199 }
00200 
00201 int
00202 netsnmp_register_long_instance(const char *name,
00203                                oid * reg_oid, size_t reg_oid_len,
00204                                long *it, Netsnmp_Node_Handler * subhandler)
00205 {
00206     netsnmp_handler_registration *myreg;
00207 
00208     myreg = get_reg(name, "long_handler", reg_oid, reg_oid_len, it,
00209                     HANDLER_CAN_RWRITE, netsnmp_instance_long_handler,
00210                     subhandler, NULL);
00211     return netsnmp_register_instance(myreg);
00212 }
00213 
00214 
00215 int
00216 netsnmp_register_read_only_uint_instance(const char *name,
00217                                          oid * reg_oid, size_t reg_oid_len,
00218                                          unsigned int *it,
00219                                          Netsnmp_Node_Handler * subhandler)
00220 {
00221     netsnmp_handler_registration *myreg;
00222 
00223     myreg = get_reg(name, "uint_handler", reg_oid, reg_oid_len, it,
00224                     HANDLER_CAN_RONLY, netsnmp_instance_uint_handler,
00225                     subhandler, NULL);
00226     return netsnmp_register_read_only_instance(myreg);
00227 }
00228 
00229 int
00230 netsnmp_register_uint_instance(const char *name,
00231                                oid * reg_oid, size_t reg_oid_len,
00232                                unsigned int *it, Netsnmp_Node_Handler * subhandler)
00233 {
00234     netsnmp_handler_registration *myreg;
00235 
00236     myreg = get_reg(name, "uint_handler", reg_oid, reg_oid_len, it,
00237                     HANDLER_CAN_RWRITE, netsnmp_instance_uint_handler,
00238                     subhandler, NULL);
00239     return netsnmp_register_instance(myreg);
00240 }
00241 
00242 int
00243 netsnmp_register_read_only_int_instance(const char *name,
00244                                 oid * reg_oid, size_t reg_oid_len,
00245                                 int *it, Netsnmp_Node_Handler * subhandler)
00246 {
00247     netsnmp_handler_registration *myreg;
00248 
00249     myreg = get_reg(name, "int_handler", reg_oid, reg_oid_len, it,
00250                     HANDLER_CAN_RONLY, netsnmp_instance_int_handler,
00251                     subhandler, NULL);
00252     return netsnmp_register_read_only_instance(myreg);
00253 }
00254 
00255   /*
00256    * Compatibility with earlier (inconsistently named) routine
00257    */
00258 int
00259 register_read_only_int_instance(const char *name,
00260                                 oid * reg_oid, size_t reg_oid_len,
00261                                 int *it, Netsnmp_Node_Handler * subhandler)
00262 {
00263   return netsnmp_register_read_only_int_instance(name,
00264                                 reg_oid, reg_oid_len,
00265                                 it, subhandler);
00266 }
00267 
00268 /*
00269  * Context registrations
00270  */
00271 
00272 int
00273 netsnmp_register_read_only_ulong_instance_context(const char *name,
00274                                                   oid * reg_oid,
00275                                                   size_t reg_oid_len,
00276                                                   u_long * it,
00277                                                   Netsnmp_Node_Handler *
00278                                                   subhandler,
00279                                                   const char *contextName)
00280 {
00281     netsnmp_handler_registration *myreg;
00282 
00283     myreg = get_reg(name, "ulong_handler", reg_oid, reg_oid_len, it,
00284                     HANDLER_CAN_RONLY, netsnmp_instance_ulong_handler,
00285                     subhandler, contextName);
00286     return netsnmp_register_read_only_instance(myreg);
00287 }
00288 
00289 int
00290 netsnmp_register_ulong_instance_context(const char *name,
00291                                         oid * reg_oid, size_t reg_oid_len,
00292                                         u_long * it,
00293                                         Netsnmp_Node_Handler * subhandler,
00294                                         const char *contextName)
00295 {
00296     netsnmp_handler_registration *myreg;
00297 
00298     myreg = get_reg(name, "ulong_handler", reg_oid, reg_oid_len, it,
00299                     HANDLER_CAN_RWRITE, netsnmp_instance_ulong_handler,
00300                     subhandler, contextName);
00301     return netsnmp_register_instance(myreg);
00302 }
00303 
00304 int
00305 netsnmp_register_read_only_counter32_instance_context(const char *name,
00306                                                       oid * reg_oid,
00307                                                       size_t reg_oid_len,
00308                                                       u_long * it,
00309                                                       Netsnmp_Node_Handler *
00310                                                       subhandler,
00311                                                       const char *contextName)
00312 {
00313     netsnmp_handler_registration *myreg;
00314 
00315     myreg = get_reg(name, "counter32_handler", reg_oid, reg_oid_len, it,
00316                     HANDLER_CAN_RONLY, netsnmp_instance_counter32_handler,
00317                     subhandler, contextName);
00318     return netsnmp_register_read_only_instance(myreg);
00319 }
00320 
00321 int
00322 netsnmp_register_read_only_long_instance_context(const char *name,
00323                                                  oid * reg_oid,
00324                                                  size_t reg_oid_len,
00325                                                  long *it,
00326                                                  Netsnmp_Node_Handler
00327                                                  *subhandler,
00328                                                  const char *contextName)
00329 {
00330     netsnmp_handler_registration *myreg;
00331 
00332     myreg = get_reg(name, "long_handler", reg_oid, reg_oid_len, it,
00333                     HANDLER_CAN_RONLY, netsnmp_instance_long_handler,
00334                     subhandler, contextName);
00335     return netsnmp_register_read_only_instance(myreg);
00336 }
00337 
00338 int
00339 netsnmp_register_long_instance_context(const char *name,
00340                                        oid * reg_oid, size_t reg_oid_len,
00341                                        long *it,
00342                                        Netsnmp_Node_Handler * subhandler,
00343                                        const char *contextName)
00344 {
00345     netsnmp_handler_registration *myreg;
00346 
00347     myreg = get_reg(name, "long_handler", reg_oid, reg_oid_len, it,
00348                     HANDLER_CAN_RWRITE, netsnmp_instance_long_handler,
00349                     subhandler, contextName);
00350     return netsnmp_register_instance(myreg);
00351 }
00352 
00353 int
00354 netsnmp_register_int_instance_context(const char *name,
00355                                       oid * reg_oid,
00356                                       size_t reg_oid_len,
00357                                       int *it,
00358                                       Netsnmp_Node_Handler * subhandler,
00359                                       const char *contextName)
00360 {
00361     netsnmp_handler_registration *myreg;
00362 
00363     myreg = get_reg(name, "int_handler", reg_oid, reg_oid_len, it,
00364                     HANDLER_CAN_RWRITE, netsnmp_instance_int_handler,
00365                     subhandler, contextName);
00366     return netsnmp_register_instance(myreg);
00367 }
00368 
00369 int
00370 netsnmp_register_read_only_int_instance_context(const char *name,
00371                                                 oid * reg_oid,
00372                                                 size_t reg_oid_len,
00373                                                 int *it,
00374                                                 Netsnmp_Node_Handler * subhandler,
00375                                                 const char *contextName)
00376 {
00377     netsnmp_handler_registration *myreg;
00378 
00379     myreg = get_reg(name, "int_handler", reg_oid, reg_oid_len, it,
00380                     HANDLER_CAN_RONLY, netsnmp_instance_int_handler,
00381                     subhandler, contextName);
00382     return netsnmp_register_read_only_instance(myreg);
00383 }
00384 
00385 /*
00386  * Compatibility with earlier (inconsistently named) routine
00387  */
00388 int
00389 register_read_only_int_instance_context(const char *name,
00390                                         oid * reg_oid, size_t reg_oid_len,
00391                                         int *it,
00392                                         Netsnmp_Node_Handler * subhandler,
00393                                         const char *contextName)
00394 {
00395     return netsnmp_register_read_only_int_instance_context(name,
00396                                                            reg_oid, reg_oid_len,
00397                                                            it, subhandler,
00398                                                            contextName);
00399 }
00400 
00401 int
00402 netsnmp_register_num_file_instance(const char *name,
00403                                    oid * reg_oid, size_t reg_oid_len,
00404                                    char *file_name, int asn_type, int mode,
00405                                    Netsnmp_Node_Handler * subhandler,
00406                                    const char *contextName)
00407 {
00408     netsnmp_handler_registration *myreg;
00409     netsnmp_num_file_instance *nfi;
00410 
00411     if ((NULL == name) || (NULL == reg_oid) || (NULL == file_name)) {
00412         snmp_log(LOG_ERR, "bad parameter to netsnmp_register_num_file_instance\n");
00413         return MIB_REGISTRATION_FAILED;
00414     }
00415 
00416     nfi = SNMP_MALLOC_TYPEDEF(netsnmp_num_file_instance);
00417     if ((NULL == nfi) ||
00418         (NULL == (nfi->file_name = strdup(file_name)))) {
00419         snmp_log(LOG_ERR, "could not not allocate memory\n");
00420         if (NULL != nfi)
00421             free(nfi); /* SNMP_FREE overkill on local var */
00422         return MIB_REGISTRATION_FAILED;
00423     }
00424 
00425     myreg = get_reg(name, "file_num_handler", reg_oid, reg_oid_len, nfi,
00426                     mode, netsnmp_instance_num_file_handler,
00427                     subhandler, contextName);
00428     if (NULL == myreg) {
00429         free(nfi); /* SNMP_FREE overkill on local var */
00430         return MIB_REGISTRATION_FAILED;
00431     }
00432 
00433     nfi->type = asn_type;
00434 
00435     if (HANDLER_CAN_RONLY == mode)
00436         return netsnmp_register_read_only_instance(myreg);
00437 
00438     return netsnmp_register_instance(myreg);
00439 }
00440 
00459 int
00460 netsnmp_register_int_instance(const char *name,
00461                               oid * reg_oid, size_t reg_oid_len,
00462                               int *it, Netsnmp_Node_Handler * subhandler)
00463 {
00464     netsnmp_handler_registration *myreg;
00465 
00466     myreg = get_reg(name, "int_handler", reg_oid, reg_oid_len, it,
00467                     HANDLER_CAN_RWRITE, netsnmp_instance_int_handler,
00468                     subhandler, NULL);
00469     return netsnmp_register_instance(myreg);
00470 }
00471 
00472 int
00473 netsnmp_instance_ulong_handler(netsnmp_mib_handler *handler,
00474                                netsnmp_handler_registration *reginfo,
00475                                netsnmp_agent_request_info *reqinfo,
00476                                netsnmp_request_info *requests)
00477 {
00478 
00479     u_long         *it = (u_long *) handler->myvoid;
00480     u_long         *it_save;
00481 
00482     DEBUGMSGTL(("netsnmp_instance_ulong_handler", "Got request:  %d\n",
00483                 reqinfo->mode));
00484 
00485     switch (reqinfo->mode) {
00486         /*
00487          * data requests 
00488          */
00489     case MODE_GET:
00490         snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
00491                                  (u_char *) it, sizeof(*it));
00492         break;
00493 
00494         /*
00495          * SET requests.  Should only get here if registered RWRITE 
00496          */
00497     case MODE_SET_RESERVE1:
00498         if (requests->requestvb->type != ASN_UNSIGNED)
00499             netsnmp_set_request_error(reqinfo, requests,
00500                                       SNMP_ERR_WRONGTYPE);
00501         break;
00502 
00503     case MODE_SET_RESERVE2:
00504         /*
00505          * store old info for undo later 
00506          */
00507         memdup((u_char **) & it_save, (u_char *) it, sizeof(u_long));
00508         if (it_save == NULL) {
00509             netsnmp_set_request_error(reqinfo, requests,
00510                                       SNMP_ERR_RESOURCEUNAVAILABLE);
00511             return SNMP_ERR_NOERROR;
00512         }
00513         netsnmp_request_add_list_data(requests,
00514                                       netsnmp_create_data_list
00515                                       (INSTANCE_HANDLER_NAME, it_save,
00516                                        free));
00517         break;
00518 
00519     case MODE_SET_ACTION:
00520         /*
00521          * update current 
00522          */
00523         DEBUGMSGTL(("testhandler", "updated u_long %ul -> %ul\n", *it,
00524                     *(requests->requestvb->val.integer)));
00525         *it = *(requests->requestvb->val.integer);
00526         break;
00527 
00528     case MODE_SET_UNDO:
00529         *it =
00530             *((u_long *) netsnmp_request_get_list_data(requests,
00531                                                        INSTANCE_HANDLER_NAME));
00532         break;
00533 
00534     case MODE_SET_COMMIT:
00535     case MODE_SET_FREE:
00536         /*
00537          * nothing to do 
00538          */
00539         break;
00540     }
00541 
00542     if (handler->next && handler->next->access_method)
00543         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00544                                          requests);
00545 
00546     return SNMP_ERR_NOERROR;
00547 }
00548 
00549 int
00550 netsnmp_instance_counter32_handler(netsnmp_mib_handler *handler,
00551                                    netsnmp_handler_registration *reginfo,
00552                                    netsnmp_agent_request_info *reqinfo,
00553                                    netsnmp_request_info *requests)
00554 {
00555 
00556     u_long         *it = (u_long *) handler->myvoid;
00557 
00558     DEBUGMSGTL(("netsnmp_instance_counter32_handler",
00559                 "Got request:  %d\n", reqinfo->mode));
00560 
00561     switch (reqinfo->mode) {
00562         /*
00563          * data requests 
00564          */
00565     case MODE_GET:
00566         snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER,
00567                                  (u_char *) it, sizeof(*it));
00568         break;
00569 
00570         /*
00571          * SET requests.  Should only get here if registered RWRITE 
00572          */
00573     default:
00574         snmp_log(LOG_ERR,
00575                  "netsnmp_instance_counter32_handler: illegal mode\n");
00576         netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR);
00577         return SNMP_ERR_NOERROR;
00578     }
00579     if (handler->next && handler->next->access_method)
00580         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00581                                          requests);
00582     return SNMP_ERR_NOERROR;
00583 }
00584 
00585 int
00586 netsnmp_instance_long_handler(netsnmp_mib_handler *handler,
00587                               netsnmp_handler_registration *reginfo,
00588                               netsnmp_agent_request_info *reqinfo,
00589                               netsnmp_request_info *requests)
00590 {
00591 
00592     long           *it = (u_long *) handler->myvoid;
00593     long           *it_save;
00594 
00595     DEBUGMSGTL(("netsnmp_instance_long_handler", "Got request:  %d\n",
00596                 reqinfo->mode));
00597 
00598     switch (reqinfo->mode) {
00599         /*
00600          * data requests 
00601          */
00602     case MODE_GET:
00603         snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
00604                                  (u_char *) it, sizeof(*it));
00605         break;
00606 
00607         /*
00608          * SET requests.  Should only get here if registered RWRITE 
00609          */
00610     case MODE_SET_RESERVE1:
00611         if (requests->requestvb->type != ASN_INTEGER)
00612             netsnmp_set_request_error(reqinfo, requests,
00613                                       SNMP_ERR_WRONGTYPE);
00614         break;
00615 
00616     case MODE_SET_RESERVE2:
00617         /*
00618          * store old info for undo later 
00619          */
00620         memdup((u_char **) & it_save, (u_char *) it, sizeof(long));
00621         if (it_save == NULL) {
00622             netsnmp_set_request_error(reqinfo, requests,
00623                                       SNMP_ERR_RESOURCEUNAVAILABLE);
00624             return SNMP_ERR_NOERROR;
00625         }
00626         netsnmp_request_add_list_data(requests,
00627                                       netsnmp_create_data_list
00628                                       (INSTANCE_HANDLER_NAME, it_save,
00629                                        free));
00630         break;
00631 
00632     case MODE_SET_ACTION:
00633         /*
00634          * update current 
00635          */
00636         DEBUGMSGTL(("testhandler", "updated u_long %ul -> %ul\n", *it,
00637                     *(requests->requestvb->val.integer)));
00638         *it = *(requests->requestvb->val.integer);
00639         break;
00640 
00641     case MODE_SET_UNDO:
00642         *it =
00643             *((u_long *) netsnmp_request_get_list_data(requests,
00644                                                        INSTANCE_HANDLER_NAME));
00645         break;
00646 
00647     case MODE_SET_COMMIT:
00648     case MODE_SET_FREE:
00649         /*
00650          * nothing to do 
00651          */
00652         break;
00653     }
00654     if (handler->next && handler->next->access_method)
00655         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00656                                          requests);
00657     return SNMP_ERR_NOERROR;
00658 }
00659 
00660 int
00661 netsnmp_instance_int_handler(netsnmp_mib_handler *handler,
00662                              netsnmp_handler_registration *reginfo,
00663                              netsnmp_agent_request_info *reqinfo,
00664                              netsnmp_request_info *requests)
00665 {
00666 
00667     int *it = (int *) handler->myvoid;
00668     int *it_save;
00669     long tmp_it;
00670     
00671     DEBUGMSGTL(("netsnmp_instance_int_handler", "Got request:  %d\n",
00672                 reqinfo->mode));
00673 
00674     switch (reqinfo->mode) {
00675         /*
00676          * data requests 
00677          */
00678     case MODE_GET:
00679         /*
00680          * Use a long here, otherwise on 64 bit use of an int would fail
00681          */
00682         tmp_it = *it;
00683         snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
00684                                  (u_char *) &tmp_it, sizeof(tmp_it));
00685         break;
00686 
00687         /*
00688          * SET requests.  Should only get here if registered RWRITE 
00689          */
00690     case MODE_SET_RESERVE1:
00691         if (requests->requestvb->type != ASN_INTEGER)
00692             netsnmp_set_request_error(reqinfo, requests,
00693                                       SNMP_ERR_WRONGTYPE);
00694         break;
00695 
00696     case MODE_SET_RESERVE2:
00697         /*
00698          * store old info for undo later 
00699          */
00700         memdup((u_char **) & it_save, (u_char *) it, sizeof(int));
00701         if (it_save == NULL) {
00702             netsnmp_set_request_error(reqinfo, requests,
00703                                       SNMP_ERR_RESOURCEUNAVAILABLE);
00704             return SNMP_ERR_NOERROR;
00705         }
00706         netsnmp_request_add_list_data(requests,
00707                                       netsnmp_create_data_list
00708                                       (INSTANCE_HANDLER_NAME, it_save,
00709                                        free));
00710         break;
00711 
00712     case MODE_SET_ACTION:
00713         /*
00714          * update current 
00715          */
00716         DEBUGMSGTL(("testhandler", "updated int %d -> %l\n", *it,
00717                     *(requests->requestvb->val.integer)));
00718         *it = (int) *(requests->requestvb->val.integer);
00719         break;
00720 
00721     case MODE_SET_UNDO:
00722         *it =
00723             *((u_int *) netsnmp_request_get_list_data(requests,
00724                                                       INSTANCE_HANDLER_NAME));
00725         break;
00726 
00727     case MODE_SET_COMMIT:
00728     case MODE_SET_FREE:
00729         /*
00730          * nothing to do 
00731          */
00732         break;
00733     }
00734     if (handler->next && handler->next->access_method)
00735         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00736                                          requests);
00737     return SNMP_ERR_NOERROR;
00738 }
00739 
00740 int
00741 netsnmp_instance_num_file_handler(netsnmp_mib_handler *handler,
00742                                   netsnmp_handler_registration *reginfo,
00743                                   netsnmp_agent_request_info *reqinfo,
00744                                   netsnmp_request_info *requests)
00745 {
00746     netsnmp_num_file_instance *nfi;
00747     u_long it, *it_save;
00748     int rc;
00749 
00750     netsnmp_assert(NULL != handler);
00751     nfi = (netsnmp_num_file_instance *)handler->myvoid;
00752     netsnmp_assert(NULL != nfi);
00753     netsnmp_assert(NULL != nfi->file_name);
00754 
00755     DEBUGMSGTL(("netsnmp_instance_int_handler", "Got request:  %d\n",
00756                 reqinfo->mode));
00757 
00758     switch (reqinfo->mode) {
00759         /*
00760          * data requests 
00761          */
00762     case MODE_GET:
00763         /*
00764          * Use a long here, otherwise on 64 bit use of an int would fail
00765          */
00766         netsnmp_assert(NULL == nfi->filep);
00767         nfi->filep = fopen(nfi->file_name, "r");
00768         if (NULL == nfi->filep) {
00769             netsnmp_set_request_error(reqinfo, requests,
00770                                       SNMP_NOSUCHINSTANCE);
00771             return SNMP_ERR_NOERROR;
00772         }
00773         rc = fscanf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
00774                     &it);
00775         fclose(nfi->filep);
00776         nfi->filep = NULL;
00777         if (rc != 1) {
00778             netsnmp_set_request_error(reqinfo, requests,
00779                                       SNMP_NOSUCHINSTANCE);
00780             return SNMP_ERR_NOERROR;
00781         }
00782         snmp_set_var_typed_value(requests->requestvb, nfi->type,
00783                                  (u_char *) &it, sizeof(it));
00784         break;
00785 
00786         /*
00787          * SET requests.  Should only get here if registered RWRITE 
00788          */
00789     case MODE_SET_RESERVE1:
00790         netsnmp_assert(NULL == nfi->filep);
00791         if (requests->requestvb->type != nfi->type)
00792             netsnmp_set_request_error(reqinfo, requests,
00793                                       SNMP_ERR_WRONGTYPE);
00794         break;
00795 
00796     case MODE_SET_RESERVE2:
00797         netsnmp_assert(NULL == nfi->filep);
00798         nfi->filep = fopen(nfi->file_name, "w+");
00799         if (NULL == nfi->filep) {
00800             netsnmp_set_request_error(reqinfo, requests,
00801                                       SNMP_ERR_NOTWRITABLE);
00802             return SNMP_ERR_NOERROR;
00803         }
00804         /*
00805          * store old info for undo later 
00806          */
00807         if (fscanf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
00808                    &it) != 1) {
00809             netsnmp_set_request_error(reqinfo, requests,
00810                                       SNMP_ERR_RESOURCEUNAVAILABLE);
00811             return SNMP_ERR_NOERROR;
00812         }
00813 
00814         memdup((u_char **) & it_save, (u_char *)&it, sizeof(u_long));
00815         if (it_save == NULL) {
00816             netsnmp_set_request_error(reqinfo, requests,
00817                                       SNMP_ERR_RESOURCEUNAVAILABLE);
00818             return SNMP_ERR_NOERROR;
00819         }
00820         netsnmp_request_add_list_data(requests,
00821                                       netsnmp_create_data_list
00822                                       (INSTANCE_HANDLER_NAME, it_save,
00823                                        free));
00824         break;
00825 
00826     case MODE_SET_ACTION:
00827         /*
00828          * update current 
00829          */
00830         DEBUGMSGTL(("helper:instance", "updated %s -> %l\n", nfi->file_name,
00831                     *(requests->requestvb->val.integer)));
00832         it = *(requests->requestvb->val.integer);
00833         rewind(nfi->filep); /* rewind to make sure we are at the beginning */
00834         rc = fprintf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
00835                      it);
00836         if (rc < 0) {
00837             netsnmp_set_request_error(reqinfo, requests,
00838                                       SNMP_ERR_GENERR);
00839             return SNMP_ERR_NOERROR;
00840         }
00841         break;
00842 
00843     case MODE_SET_UNDO:
00844         it =
00845             *((u_int *) netsnmp_request_get_list_data(requests,
00846                                                       INSTANCE_HANDLER_NAME));
00847         rc = fprintf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
00848                      it);
00849         if (rc < 0)
00850             netsnmp_set_request_error(reqinfo, requests,
00851                                       SNMP_ERR_UNDOFAILED);
00854     case MODE_SET_COMMIT:
00855     case MODE_SET_FREE:
00856         if (NULL != nfi->filep) {
00857             fclose(nfi->filep);
00858             nfi->filep = NULL;
00859         }
00860         break;
00861     }
00862 
00863     if (handler->next && handler->next->access_method)
00864         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00865                                          requests);
00866     return SNMP_ERR_NOERROR;
00867 }
00868 
00869 int
00870 netsnmp_instance_uint_handler(netsnmp_mib_handler *handler,
00871                               netsnmp_handler_registration *reginfo,
00872                               netsnmp_agent_request_info *reqinfo,
00873                               netsnmp_request_info *requests)
00874 {
00875 
00876     unsigned int *it = (unsigned int *) handler->myvoid;
00877     unsigned int *it_save;
00878     unsigned long tmp_it;
00879     
00880     DEBUGMSGTL(("netsnmp_instance_uint_handler", "Got request:  %d\n",
00881                 reqinfo->mode));
00882 
00883     switch (reqinfo->mode) {
00884         /*
00885          * data requests 
00886          */
00887     case MODE_GET:
00888         /*
00889          * Use a long here, otherwise on 64 bit use of an int would fail
00890          */
00891         tmp_it = *it;
00892         snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
00893                                  (u_char *) &tmp_it, sizeof(unsigned long));
00894         break;
00895 
00896         /*
00897          * SET requests.  Should only get here if registered RWRITE 
00898          */
00899     case MODE_SET_RESERVE1:
00900         if (requests->requestvb->type != ASN_UNSIGNED)
00901             netsnmp_set_request_error(reqinfo, requests,
00902                                       SNMP_ERR_WRONGTYPE);
00903         break;
00904 
00905     case MODE_SET_RESERVE2:
00906         /*
00907          * store old info for undo later 
00908          */
00909         memdup((u_char **) & it_save, (u_char *) it, sizeof(u_int));
00910         if (it_save == NULL) {
00911             netsnmp_set_request_error(reqinfo, requests,
00912                                       SNMP_ERR_RESOURCEUNAVAILABLE);
00913             return SNMP_ERR_NOERROR;
00914         }
00915         netsnmp_request_add_list_data(requests,
00916                                       netsnmp_create_data_list
00917                                       (INSTANCE_HANDLER_NAME, it_save,
00918                                        free));
00919         break;
00920 
00921     case MODE_SET_ACTION:
00922         /*
00923          * update current 
00924          */
00925         DEBUGMSGTL(("testhandler", "updated uint %d -> %l\n", *it,
00926                     *(requests->requestvb->val.integer)));
00927         *it = (unsigned int) *(requests->requestvb->val.integer);
00928         break;
00929 
00930     case MODE_SET_UNDO:
00931         *it =
00932             *((u_int *) netsnmp_request_get_list_data(requests,
00933                                                       INSTANCE_HANDLER_NAME));
00934         break;
00935 
00936     case MODE_SET_COMMIT:
00937     case MODE_SET_FREE:
00938         /*
00939          * nothing to do 
00940          */
00941         break;
00942     }
00943     if (handler->next && handler->next->access_method)
00944         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00945                                          requests);
00946     return SNMP_ERR_NOERROR;
00947 }
00948 
00949 int
00950 netsnmp_instance_helper_handler(netsnmp_mib_handler *handler,
00951                                 netsnmp_handler_registration *reginfo,
00952                                 netsnmp_agent_request_info *reqinfo,
00953                                 netsnmp_request_info *requests)
00954 {
00955 
00956     netsnmp_variable_list *var = requests->requestvb;
00957 
00958     int             ret, cmp;
00959 
00960     DEBUGMSGTL(("helper:instance", "Got request:\n"));
00961     cmp = snmp_oid_compare(requests->requestvb->name,
00962                            requests->requestvb->name_length,
00963                            reginfo->rootoid, reginfo->rootoid_len);
00964 
00965     DEBUGMSGTL(("helper:instance", "  oid:", cmp));
00966     DEBUGMSGOID(("helper:instance", var->name, var->name_length));
00967     DEBUGMSG(("helper:instance", "\n"));
00968 
00969     switch (reqinfo->mode) {
00970     case MODE_GET:
00971         if (cmp != 0) {
00972             netsnmp_set_request_error(reqinfo, requests,
00973                                       SNMP_NOSUCHINSTANCE);
00974             return SNMP_ERR_NOERROR;
00975         } else {
00976             return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00977                                              requests);
00978         }
00979         break;
00980 
00981     case MODE_SET_RESERVE1:
00982     case MODE_SET_RESERVE2:
00983     case MODE_SET_ACTION:
00984     case MODE_SET_COMMIT:
00985     case MODE_SET_UNDO:
00986     case MODE_SET_FREE:
00987         if (cmp != 0) {
00988             netsnmp_set_request_error(reqinfo, requests,
00989                                       SNMP_ERR_NOCREATION);
00990             return SNMP_ERR_NOERROR;
00991         } else {
00992             return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00993                                              requests);
00994         }
00995         break;
00996 
00997     case MODE_GETNEXT:
00998         if (cmp < 0 || (cmp == 0 && requests->inclusive)) {
00999             reqinfo->mode = MODE_GET;
01000             snmp_set_var_objid(requests->requestvb, reginfo->rootoid,
01001                                reginfo->rootoid_len);
01002             ret =
01003                 netsnmp_call_next_handler(handler, reginfo, reqinfo,
01004                                           requests);
01005             reqinfo->mode = MODE_GETNEXT;
01006             /*
01007              * if the instance doesn't have data, set type to ASN_NULL
01008              * to move to the next sub-tree. Ignore delegated requests; they
01009              * might have data later on.
01010              */
01011             if (!requests->delegated &&
01012                 (requests->requestvb->type == SNMP_NOSUCHINSTANCE ||
01013                  requests->requestvb->type == SNMP_NOSUCHOBJECT)) {
01014                 requests->requestvb->type = ASN_NULL;
01015             }
01016             return ret;
01017         } else {
01018             return SNMP_ERR_NOERROR;
01019         }
01020         break;
01021     }
01022     /*
01023      * got here only if illegal mode found 
01024      */
01025     return SNMP_ERR_GENERR;
01026 }
01027