net-snmp 5.7
old_api.c
00001 #include <net-snmp/net-snmp-config.h>
00002 
00003 #include <net-snmp/net-snmp-includes.h>
00004 #include <net-snmp/agent/net-snmp-agent-includes.h>
00005 
00006 #include <net-snmp/agent/old_api.h>
00007 
00008 #if HAVE_STRING_H
00009 #include <string.h>
00010 #else
00011 #include <strings.h>
00012 #endif
00013 
00014 #include <net-snmp/agent/agent_callbacks.h>
00015 
00016 #include <stddef.h>
00017 
00018 #define MIB_CLIENTS_ARE_EVIL 1
00019 
00020 #ifdef HAVE_DMALLOC_H
00021 static void free_wrapper(void * p)
00022 {
00023     free(p);
00024 }
00025 #else
00026 #define free_wrapper free
00027 #endif
00028 
00029 /*
00030  * don't use these! 
00031  */
00032 void            set_current_agent_session(netsnmp_agent_session *asp);
00033 netsnmp_agent_session *netsnmp_get_current_agent_session(void);
00034 
00048 netsnmp_mib_handler *
00049 get_old_api_handler(void)
00050 {
00051     return netsnmp_create_handler("old_api", netsnmp_old_api_helper);
00052 }
00053 
00054 struct variable *
00055 netsnmp_duplicate_variable(struct variable *var)
00056 {
00057     struct variable *var2 = NULL;
00058     
00059     if (var) {
00060         const int varsize = offsetof(struct variable, name) + var->namelen * sizeof(var->name[0]);
00061         var2 = malloc(varsize);
00062         if (var2)
00063             memcpy(var2, var, varsize);
00064     }
00065     return var2;
00066 }
00067 
00072 int
00073 netsnmp_register_old_api(const char *moduleName,
00074                          struct variable *var,
00075                          size_t varsize,
00076                          size_t numvars,
00077                          const oid * mibloc,
00078                          size_t mibloclen,
00079                          int priority,
00080                          int range_subid,
00081                          oid range_ubound,
00082                          netsnmp_session * ss,
00083                          const char *context, int timeout, int flags)
00084 {
00085 
00086     unsigned int    i;
00087 
00088     /*
00089      * register all subtree nodes 
00090      */
00091     for (i = 0; i < numvars; i++) {
00092         struct variable *vp;
00093         netsnmp_handler_registration *reginfo =
00094             SNMP_MALLOC_TYPEDEF(netsnmp_handler_registration);
00095         if (reginfo == NULL)
00096             return SNMP_ERR_GENERR;
00097 
00098         vp = netsnmp_duplicate_variable((struct variable *)
00099                                         ((char *) var + varsize * i));
00100 
00101         reginfo->handler = get_old_api_handler();
00102         reginfo->handlerName = strdup(moduleName);
00103         reginfo->rootoid_len = (mibloclen + vp->namelen);
00104         reginfo->rootoid =
00105             (oid *) malloc(reginfo->rootoid_len * sizeof(oid));
00106         if (reginfo->rootoid == NULL)
00107             return SNMP_ERR_GENERR;
00108 
00109         memcpy(reginfo->rootoid, mibloc, mibloclen * sizeof(oid));
00110         memcpy(reginfo->rootoid + mibloclen, vp->name, vp->namelen
00111                * sizeof(oid));
00112         reginfo->handler->myvoid = (void *) vp;
00113         reginfo->handler->data_clone
00114             = (void *(*)(void *))netsnmp_duplicate_variable;
00115         reginfo->handler->data_free = free;
00116 
00117         reginfo->priority = priority;
00118         reginfo->range_subid = range_subid;
00119 
00120         reginfo->range_ubound = range_ubound;
00121         reginfo->timeout = timeout;
00122         reginfo->contextName = (context) ? strdup(context) : NULL;
00123         reginfo->modes = HANDLER_CAN_RWRITE;
00124 
00125         /*
00126          * register ourselves in the mib tree 
00127          */
00128         if (netsnmp_register_handler(reginfo) != MIB_REGISTERED_OK) {
00130             SNMP_FREE(vp);
00131         }
00132     }
00133     return SNMPERR_SUCCESS;
00134 }
00135 
00137 int
00138 netsnmp_register_mib_table_row(const char *moduleName,
00139                                struct variable *var,
00140                                size_t varsize,
00141                                size_t numvars,
00142                                oid * mibloc,
00143                                size_t mibloclen,
00144                                int priority,
00145                                int var_subid,
00146                                netsnmp_session * ss,
00147                                const char *context, int timeout, int flags)
00148 {
00149     unsigned int    i = 0, rc = 0;
00150     oid             ubound = 0;
00151 
00152     for (i = 0; i < numvars; i++) {
00153         struct variable *vr =
00154             (struct variable *) ((char *) var + (i * varsize));
00155         netsnmp_handler_registration *r;
00156         if ( var_subid > (int)mibloclen ) {
00157             break;    /* doesn't make sense */
00158         }
00159         r = SNMP_MALLOC_TYPEDEF(netsnmp_handler_registration);
00160 
00161         if (r == NULL) {
00162             /*
00163              * Unregister whatever we have registered so far, and
00164              * return an error.  
00165              */
00166             rc = MIB_REGISTRATION_FAILED;
00167             break;
00168         }
00169         memset(r, 0, sizeof(netsnmp_handler_registration));
00170 
00171         r->handler = get_old_api_handler();
00172         r->handlerName = strdup(moduleName);
00173 
00174         if (r->handlerName == NULL) {
00175             netsnmp_handler_registration_free(r);
00176             break;
00177         }
00178 
00179         r->rootoid_len = mibloclen;
00180         r->rootoid = (oid *) malloc(r->rootoid_len * sizeof(oid));
00181 
00182         if (r->rootoid == NULL) {
00183             netsnmp_handler_registration_free(r);
00184             rc = MIB_REGISTRATION_FAILED;
00185             break;
00186         }
00187         memcpy(r->rootoid, mibloc, mibloclen * sizeof(oid));
00188         memcpy((u_char *) (r->rootoid + (var_subid - vr->namelen)), vr->name,
00189                vr->namelen * sizeof(oid));
00190         DEBUGMSGTL(("netsnmp_register_mib_table_row", "rootoid "));
00191         DEBUGMSGOID(("netsnmp_register_mib_table_row", r->rootoid,
00192                      r->rootoid_len));
00193         DEBUGMSG(("netsnmp_register_mib_table_row", "(%d)\n",
00194                      (var_subid - vr->namelen)));
00195         r->handler->myvoid = netsnmp_duplicate_variable(vr);
00196         r->handler->data_clone = (void *(*)(void *))netsnmp_duplicate_variable;
00197         r->handler->data_free = free;
00198 
00199         if (r->handler->myvoid == NULL) {
00200             netsnmp_handler_registration_free(r);
00201             rc = MIB_REGISTRATION_FAILED;
00202             break;
00203         }
00204 
00205         r->contextName = (context) ? strdup(context) : NULL;
00206 
00207         if (context != NULL && r->contextName == NULL) {
00208             netsnmp_handler_registration_free(r);
00209             rc = MIB_REGISTRATION_FAILED;
00210             break;
00211         }
00212 
00213         r->priority = priority;
00214         r->range_subid = 0;     /* var_subid; */
00215         r->range_ubound = 0;    /* range_ubound; */
00216         r->timeout = timeout;
00217         r->modes = HANDLER_CAN_RWRITE;
00218 
00219         /*
00220          * Register this column and row  
00221          */
00222         if ((rc =
00223              netsnmp_register_handler_nocallback(r)) !=
00224             MIB_REGISTERED_OK) {
00225             DEBUGMSGTL(("netsnmp_register_mib_table_row",
00226                         "register failed %d\n", rc));
00227             netsnmp_handler_registration_free(r);
00228             break;
00229         }
00230 
00231         if (vr->namelen > 0) {
00232             if (vr->name[vr->namelen - 1] > ubound) {
00233                 ubound = vr->name[vr->namelen - 1];
00234             }
00235         }
00236     }
00237 
00238     if (rc == MIB_REGISTERED_OK) {
00239         struct register_parameters reg_parms;
00240 
00241         reg_parms.name = mibloc;
00242         reg_parms.namelen = mibloclen;
00243         reg_parms.priority = priority;
00244         reg_parms.flags = (u_char) flags;
00245         reg_parms.range_subid = var_subid;
00246         reg_parms.range_ubound = ubound;
00247         reg_parms.timeout = timeout;
00248         reg_parms.contextName = context;
00249         rc = snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
00250                                  SNMPD_CALLBACK_REGISTER_OID, &reg_parms);
00251     }
00252 
00253     return rc;
00254 }
00255 
00257 int
00258 netsnmp_old_api_helper(netsnmp_mib_handler *handler,
00259                        netsnmp_handler_registration *reginfo,
00260                        netsnmp_agent_request_info *reqinfo,
00261                        netsnmp_request_info *requests)
00262 {
00263 
00264 #if MIB_CLIENTS_ARE_EVIL
00265     oid             save[MAX_OID_LEN];
00266     size_t          savelen = 0;
00267 #endif
00268     struct variable compat_var, *cvp = &compat_var;
00269     int             exact = 1;
00270     int             status;
00271 
00272     struct variable *vp;
00273     netsnmp_old_api_cache *cacheptr;
00274     netsnmp_agent_session *oldasp = NULL;
00275     u_char         *access = NULL;
00276     WriteMethod    *write_method = NULL;
00277     size_t          len;
00278     size_t          tmp_len;
00279     oid             tmp_name[MAX_OID_LEN];
00280 
00281     vp = (struct variable *) handler->myvoid;
00282 
00283     /*
00284      * create old variable structure with right information 
00285      */
00286     memcpy(cvp->name, reginfo->rootoid,
00287            reginfo->rootoid_len * sizeof(oid));
00288     cvp->namelen = reginfo->rootoid_len;
00289     cvp->type = vp->type;
00290     cvp->magic = vp->magic;
00291     cvp->acl = vp->acl;
00292     cvp->findVar = vp->findVar;
00293 
00294     switch (reqinfo->mode) {
00295     case MODE_GETNEXT:
00296     case MODE_GETBULK:
00297         exact = 0;
00298     }
00299 
00300     for (; requests; requests = requests->next) {
00301 
00302 #if MIB_CLIENTS_ARE_EVIL
00303         savelen = requests->requestvb->name_length;
00304         memcpy(save, requests->requestvb->name, savelen * sizeof(oid));
00305 #endif
00306 
00307         switch (reqinfo->mode) {
00308         case MODE_GET:
00309         case MODE_GETNEXT:
00310 #ifndef NETSNMP_NO_WRITE_SUPPORT
00311         case MODE_SET_RESERVE1:
00312 #endif /* !NETSNMP_NO_WRITE_SUPPORT */
00313             /*
00314              * Actually call the old mib-module function 
00315              */
00316             if (vp && vp->findVar) {
00317                 memcpy(tmp_name, requests->requestvb->name,
00318                                  requests->requestvb->name_length*sizeof(oid));
00319                 tmp_len = requests->requestvb->name_length;
00320                 access = (*(vp->findVar)) (cvp, tmp_name, &tmp_len,
00321                                            exact, &len, &write_method);
00322                 snmp_set_var_objid( requests->requestvb, tmp_name, tmp_len );
00323             }
00324             else
00325                 access = NULL;
00326 
00327 #ifdef WWW_FIX
00328             if (IS_DELEGATED(cvp->type)) {
00329                 add_method = (AddVarMethod *) statP;
00330                 requests->delayed = 1;
00331                 have_delegated = 1;
00332                 continue;       /* WWW: This may not get to the right place */
00333             }
00334 #endif
00335 
00336             /*
00337              * WWW: end range checking 
00338              */
00339             if (access) {
00340                 /*
00341                  * result returned 
00342                  */
00343 #ifndef NETSNMP_NO_WRITE_SUPPORT
00344                 if (reqinfo->mode != MODE_SET_RESERVE1)
00345 #endif /* !NETSNMP_NO_WRITE_SUPPORT */
00346                     snmp_set_var_typed_value(requests->requestvb,
00347                                              cvp->type, access, len);
00348             } else {
00349                 /*
00350                  * no result returned 
00351                  */
00352 #if MIB_CLIENTS_ARE_EVIL
00353                 if (access == NULL) {
00354                     if (netsnmp_oid_equals(requests->requestvb->name,
00355                                          requests->requestvb->name_length,
00356                                          save, savelen) != 0) {
00357                         DEBUGMSGTL(("old_api", "evil_client: %s\n",
00358                                     reginfo->handlerName));
00359                         memcpy(requests->requestvb->name, save,
00360                                savelen * sizeof(oid));
00361                         requests->requestvb->name_length = savelen;
00362                     }
00363                 }
00364 #endif
00365             }
00366 
00367             /*
00368              * AAA: fall through for everything that is a set (see BBB) 
00369              */
00370 #ifndef NETSNMP_NO_WRITE_SUPPORT
00371             if (reqinfo->mode != MODE_SET_RESERVE1)
00372 #endif /* !NETSNMP_NO_WRITE_SUPPORT */
00373                 break;
00374 
00375             cacheptr = SNMP_MALLOC_TYPEDEF(netsnmp_old_api_cache);
00376             if (!cacheptr)
00377                 return netsnmp_set_request_error(reqinfo, requests,
00378                                                  SNMP_ERR_RESOURCEUNAVAILABLE);
00379             cacheptr->data = access;
00380             cacheptr->write_method = write_method;
00381             write_method = NULL;
00382             netsnmp_request_add_list_data(requests,
00383                                           netsnmp_create_data_list
00384                                           (OLD_API_NAME, cacheptr,
00385                                            &free_wrapper));
00386             /*
00387              * BBB: fall through for everything that is a set (see AAA) 
00388              */
00389 
00390         default:
00391             /*
00392              * WWW: explicitly list the SET conditions 
00393              */
00394             /*
00395              * (the rest of the) SET contions 
00396              */
00397             cacheptr =
00398                 (netsnmp_old_api_cache *)
00399                 netsnmp_request_get_list_data(requests, OLD_API_NAME);
00400 
00401             if (cacheptr == NULL || cacheptr->write_method == NULL) {
00402                 /*
00403                  * WWW: try to set ourselves if possible? 
00404                  */
00405                 return netsnmp_set_request_error(reqinfo, requests,
00406                                                  SNMP_ERR_NOTWRITABLE);
00407             }
00408 
00409             oldasp = netsnmp_get_current_agent_session();
00410             set_current_agent_session(reqinfo->asp);
00411             status =
00412                 (*(cacheptr->write_method)) (reqinfo->mode,
00413                                              requests->requestvb->val.
00414                                              string,
00415                                              requests->requestvb->type,
00416                                              requests->requestvb->val_len,
00417                                              cacheptr->data,
00418                                              requests->requestvb->name,
00419                                              requests->requestvb->
00420                                              name_length);
00421             set_current_agent_session(oldasp);
00422 
00423             if (status != SNMP_ERR_NOERROR) {
00424                 netsnmp_set_request_error(reqinfo, requests, status);
00425             }
00426 
00427             /*
00428              * clean up is done by the automatic freeing of the
00429              * cache stored in the request. 
00430              */
00431 
00432             break;
00433         }
00434     }
00435     return SNMP_ERR_NOERROR;
00436 }
00437 
00440 /*
00441  * don't use this! 
00442  */
00443 static netsnmp_agent_session *current_agent_session = NULL;
00444 netsnmp_agent_session *
00445 netsnmp_get_current_agent_session(void)
00446 {
00447     return current_agent_session;
00448 }
00449 
00450 /*
00451  * don't use this! 
00452  */
00453 void
00454 set_current_agent_session(netsnmp_agent_session *asp)
00455 {
00456     current_agent_session = asp;
00457 }