nfs-ganesha 1.4

instance_handler.c

Go to the documentation of this file.
00001 
00008 #ifdef HAVE_CONFIG_H
00009 #include "config.h"
00010 #endif
00011 
00012 #include <net-snmp/net-snmp-config.h>
00013 #include <net-snmp/net-snmp-includes.h>
00014 #include <net-snmp/agent/net-snmp-agent-includes.h>
00015 
00016 #include <pthread.h>
00017 
00018 #include "parse_type.h"
00019 #include "get_set_proc.h"
00020 
00022 extern register_info *register_info_list;
00023 extern int root_oid_len;
00024 
00025 /* Because I/O procedures are registered like scalars we need to check access.
00026    If we are a procedure input/output, check the trigger value and send error if need */
00027 static int check_procedure_access(netsnmp_handler_registration * reginfo)
00028 {
00029   register_info *info;
00030 
00031   /* XXX
00032    *  In order to check type of current node, we use it length.
00033    *  This parameter will change after each modification in the tree structure.
00034    *  
00035    *  conf_stat_len is the length of a val element if the node is a stat or a conf.
00036    *  numproc_pos is the numproc position in the oid for a procedure node.
00037    */
00038   int conf_stat_len = root_oid_len + 5;
00039   int numproc_pos = reginfo->rootoid_len - 5;
00040 
00041   if(reginfo->rootoid_len == conf_stat_len)
00042     /* we are a stat or conf, nothing to do */
00043     return 0;
00044 
00045   for(info = register_info_list; info; info = info->next)
00046     if(info->type == PROC &&
00047        info->function_info.proc->num == reginfo->rootoid[numproc_pos])
00048       break;
00049 
00050   if(!info || info->function_info.proc->trigger == SNMP_ADM_PROGRESS
00051      || info->function_info.proc->trigger == SNMP_ADM_DONE
00052      || info->function_info.proc->trigger == SNMP_ADM_ERROR)
00053     return 1;
00054   return 0;
00055 
00056 }
00057 
00058 int instance_string_handler(netsnmp_mib_handler * handler,
00059                             netsnmp_handler_registration * reginfo,
00060                             netsnmp_agent_request_info * reqinfo,
00061                             netsnmp_request_info * requests)
00062 {
00063   int len;
00064 
00065   switch (reqinfo->mode)
00066     {
00067       /*
00068        * data requests
00069        */
00070     case MODE_GET:
00071       snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
00072                                (u_char *) handler->myvoid, strlen(handler->myvoid));
00073       break;
00074 
00075     case MODE_SET_ACTION:
00076       /*
00077        * update current
00078        */
00079       if(check_procedure_access(reginfo))
00080         {
00081           netsnmp_request_set_error(requests, SNMP_ERR_READONLY);
00082           return SNMP_ERR_READONLY;
00083         }
00084 
00085       len = strlen((char *)requests->requestvb->val.string);
00086       if(len > SNMP_ADM_MAX_STR)
00087         netsnmp_request_set_error(requests, SNMP_ERR_BADVALUE);
00088       else
00089         {
00090           strncpy(handler->myvoid, (char *)(requests->requestvb->val.string), len);
00091           ((char *)(handler->myvoid))[len] = '\0';      /* just to be sure */
00092         }
00093       break;
00094       /* XXX
00095          do not add a default case otherwise netsnmp will never send SET_ACTION (because SET_RESERVE is considered
00096          as failed) see AGENT.txt section 8
00097        */
00098 
00099     }
00100   return SNMP_ERR_NOERROR;
00101 }
00102 
00103 int instance_int_handler(netsnmp_mib_handler * handler,
00104                          netsnmp_handler_registration * reginfo,
00105                          netsnmp_agent_request_info * reqinfo,
00106                          netsnmp_request_info * requests)
00107 {
00108   int *it = (int *)handler->myvoid;
00109 
00110   switch (reqinfo->mode)
00111     {
00112       /*
00113        * data requests
00114        */
00115     case MODE_GET:
00116       snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
00117                                (u_char *) it, sizeof(*it));
00118       break;
00119 
00120     case MODE_SET_ACTION:
00121       /*
00122        * update current
00123        */
00124       if(check_procedure_access(reginfo))
00125         {
00126           netsnmp_request_set_error(requests, SNMP_ERR_READONLY);
00127           return SNMP_ERR_READONLY;
00128         }
00129 
00130       *it = (int)*(requests->requestvb->val.integer);
00131       break;
00132 
00133     }
00134   return SNMP_ERR_NOERROR;
00135 }
00136 
00137 int instance_real_handler(netsnmp_mib_handler * handler,
00138                           netsnmp_handler_registration * reginfo,
00139                           netsnmp_agent_request_info * reqinfo,
00140                           netsnmp_request_info * requests)
00141 {
00142   int err;
00143   double *it = (double *)handler->myvoid;
00144   double tmp_it;
00145   char str[256];
00146 
00147   switch (reqinfo->mode)
00148     {
00149       /*
00150        * data requests
00151        */
00152     case MODE_GET:
00153       err = real2str(str, *it);
00154       if(!err)
00155         snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
00156                                  (u_char *) str, strlen(str));
00157       else
00158         netsnmp_request_set_error(requests, SNMP_ERR_BADVALUE);
00159       break;
00160 
00161     case MODE_SET_ACTION:
00162       /*
00163        * update current
00164        */
00165       if(check_procedure_access(reginfo))
00166         {
00167           netsnmp_request_set_error(requests, SNMP_ERR_READONLY);
00168           return SNMP_ERR_READONLY;
00169         }
00170       err = str2real(&tmp_it, (char *)(requests->requestvb->val.string));
00171       if(!err)
00172         *it = tmp_it;
00173       else
00174         netsnmp_request_set_error(requests, SNMP_ERR_BADVALUE);
00175 
00176       break;
00177 
00178     }
00179   return SNMP_ERR_NOERROR;
00180 }
00181 
00182 int instance_bigint_handler(netsnmp_mib_handler * handler,
00183                             netsnmp_handler_registration * reginfo,
00184                             netsnmp_agent_request_info * reqinfo,
00185                             netsnmp_request_info * requests)
00186 {
00187   int err;
00188   int64_t *it = (int64_t *) handler->myvoid;
00189   int64_t tmp_it;
00190   char str[256];
00191 
00192   switch (reqinfo->mode)
00193     {
00194       /*
00195        * data requests
00196        */
00197     case MODE_GET:
00198       err = big2str(str, *it);
00199       if(!err)
00200         snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
00201                                  (u_char *) str, strlen(str));
00202       else
00203         netsnmp_request_set_error(requests, SNMP_ERR_BADVALUE);
00204       break;
00205 
00206     case MODE_SET_ACTION:
00207       /*
00208        * update current
00209        */
00210       if(check_procedure_access(reginfo))
00211         {
00212           netsnmp_request_set_error(requests, SNMP_ERR_READONLY);
00213           return SNMP_ERR_READONLY;
00214         }
00215       err = str2big(&tmp_it, (char *)(requests->requestvb->val.string));
00216       if(!err)
00217         *it = tmp_it;
00218       else
00219         netsnmp_request_set_error(requests, SNMP_ERR_BADVALUE);
00220 
00221       break;
00222 
00223     }
00224   return SNMP_ERR_NOERROR;
00225 }
00226 
00227 int instance_time_handler(netsnmp_mib_handler * handler,
00228                           netsnmp_handler_registration * reginfo,
00229                           netsnmp_agent_request_info * reqinfo,
00230                           netsnmp_request_info * requests)
00231 {
00232   unsigned int *it = (unsigned int *)handler->myvoid;
00233   unsigned int tmp_it;
00234 
00235   switch (reqinfo->mode)
00236     {
00237       /*
00238        * data requests
00239        */
00240     case MODE_GET:
00241       tmp_it = (*it) * 100;
00242       snmp_set_var_typed_value(requests->requestvb, ASN_TIMETICKS,
00243                                (u_char *) & tmp_it, sizeof(tmp_it));
00244       break;
00245 
00246     case MODE_SET_ACTION:
00247       /*
00248        * update current
00249        */
00250       if(check_procedure_access(reginfo))
00251         {
00252           netsnmp_request_set_error(requests, SNMP_ERR_READONLY);
00253           return SNMP_ERR_READONLY;
00254         }
00255       tmp_it = *((unsigned int *)(requests->requestvb->val.integer));
00256       *it = tmp_it / 100;
00257       break;
00258 
00259       break;
00260 
00261     }
00262   return SNMP_ERR_NOERROR;
00263 }
00264 
00265 int instance_ip_handler(netsnmp_mib_handler * handler,
00266                         netsnmp_handler_registration * reginfo,
00267                         netsnmp_agent_request_info * reqinfo,
00268                         netsnmp_request_info * requests)
00269 {
00270   in_addr_t *it = (in_addr_t *) handler->myvoid;
00271 
00272   switch (reqinfo->mode)
00273     {
00274       /*
00275        * data requests
00276        */
00277     case MODE_GET:
00278       snmp_set_var_typed_value(requests->requestvb, ASN_IPADDRESS,
00279                                (u_char *) it, sizeof(*it));
00280       break;
00281 
00282     case MODE_SET_ACTION:
00283       /*
00284        * update current
00285        */
00286       if(check_procedure_access(reginfo))
00287         {
00288           netsnmp_request_set_error(requests, SNMP_ERR_READONLY);
00289           return SNMP_ERR_READONLY;
00290         }
00291       memcpy(it, requests->requestvb->val.string, sizeof(*it));
00292       break;
00293     }
00294   return SNMP_ERR_NOERROR;
00295 }
00296 
00297 int instance_get_set_handler(netsnmp_mib_handler * handler,
00298                              netsnmp_handler_registration * reginfo,
00299                              netsnmp_agent_request_info * reqinfo,
00300                              netsnmp_request_info * requests)
00301 {
00302 
00303   snmp_adm_type_union var;
00304   unsigned char type;
00305   register_info *info = NULL;
00306   int branch, num_stat_conf, err = 0, err_fct;
00307   char str[256];
00308   unsigned int tmp_it;
00309 
00313   /* what node do you want? */
00314   num_stat_conf = reginfo->rootoid[reginfo->rootoid_len - 3];
00315   branch = reginfo->rootoid[reginfo->rootoid_len - 4];
00316 
00317   /* look for our get_set */
00318   for(info = register_info_list; info; info = info->next)
00319     if(info->type == GET_SET &&
00320        info->function_info.get_set->num == num_stat_conf &&
00321        info->function_info.get_set->branch == branch)
00322       break;
00323 
00324   if(!info)
00325     {                           /* not found */
00326       netsnmp_request_set_error(requests, SNMP_ERR_GENERR);
00327       return SNMP_ERR_GENERR;
00328     }
00329 
00330   type = info->function_info.get_set->type;
00331 
00332   switch (reqinfo->mode)
00333     {
00334     case MODE_GET:
00335       /*
00336        * data requests
00337        */
00338       /* call the function */
00339       err =
00340           info->function_info.get_set->getter(&var, info->function_info.get_set->opt_arg);
00341       if(err)
00342         {
00343           snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
00344                                    (u_char *) "SNMP_ADM_ERROR", strlen("SNMP_ADM_ERROR"));
00345 
00346           return SNMP_ERR_NOERROR;
00347         }
00348       switch (type)
00349         {
00350         case SNMP_ADM_INTEGER:
00351           snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
00352                                    (u_char *) & (var.integer), sizeof(var.integer));
00353           break;
00354         case SNMP_ADM_STRING:
00355           snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
00356                                    (u_char *) var.string, strlen((char *)var.string));
00357           break;
00358         case SNMP_ADM_REAL:
00359           err = real2str(str, var.real);
00360           if(!err)
00361             snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
00362                                      (u_char *) str, strlen(str));
00363           else
00364             netsnmp_request_set_error(requests, SNMP_ERR_BADVALUE);
00365           break;
00366         case SNMP_ADM_BIGINT:
00367           err = big2str(str, var.bigint);
00368           if(!err)
00369             snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
00370                                      (u_char *) str, strlen(str));
00371           else
00372             netsnmp_request_set_error(requests, SNMP_ERR_BADVALUE);
00373           break;
00374         case SNMP_ADM_TIMETICKS:
00375           tmp_it = (var.time) * 100;
00376 
00377           snmp_set_var_typed_value(requests->requestvb, ASN_TIMETICKS,
00378                                    (u_char *) & (tmp_it), sizeof(tmp_it));
00379           break;
00380 
00381         default:
00382           netsnmp_request_set_error(requests, SNMP_ERR_BADVALUE);
00383         }
00384 
00385       break;
00386     case MODE_SET_ACTION:
00387       switch (type)
00388         {
00389         case SNMP_ADM_INTEGER:
00390           var.integer = *(int *)requests->requestvb->val.integer;
00391           break;
00392         case SNMP_ADM_STRING:
00393           strncpy(var.string, (char *)(requests->requestvb->val.string),
00394                   SNMP_ADM_MAX_STR);
00395           break;
00396         case SNMP_ADM_REAL:
00397           err = str2real(&(var.real), (char *)(requests->requestvb->val.string));
00398           break;
00399         case SNMP_ADM_BIGINT:
00400           err = str2big(&(var.bigint), (char *)(requests->requestvb->val.string));
00401           break;
00402         case SNMP_ADM_TIMETICKS:
00403           tmp_it = *(unsigned int *)requests->requestvb->val.integer;
00404           var.time = tmp_it / 100;
00405           break;
00406         default:
00407           netsnmp_request_set_error(requests, SNMP_ERR_BADVALUE);
00408         }
00409 
00410       if(!err)
00411         {
00412           /* call the function */
00413           err_fct =
00414               info->function_info.get_set->setter(&var,
00415                                                   info->function_info.get_set->opt_arg);
00416 
00417           if(err_fct)
00418             netsnmp_request_set_error(requests, SNMP_ERR_BADVALUE);
00419         }
00420       else
00421         netsnmp_request_set_error(requests, SNMP_ERR_BADVALUE);
00422       break;
00423     }
00424 
00425   return SNMP_ERR_NOERROR;
00426 }
00427 
00428 static void *launch_proc(void *arg)
00429 {
00430   proc_info *pinfo = arg;
00431   int err;
00432 
00433   pinfo->trigger = SNMP_ADM_PROGRESS;
00434   err =
00435       pinfo->myproc((const snmp_adm_type_union **)pinfo->inputs, pinfo->outputs,
00436                     pinfo->opt_arg);
00437 
00438   if(err)
00439     pinfo->trigger = SNMP_ADM_ERROR;
00440   else
00441     pinfo->trigger = SNMP_ADM_DONE;
00442 
00443   return NULL;
00444 }
00445 
00446 int instance_proc_handler(netsnmp_mib_handler * handler,
00447                           netsnmp_handler_registration * reginfo,
00448                           netsnmp_agent_request_info * reqinfo,
00449                           netsnmp_request_info * requests)
00450 {
00451   register_info *info;
00452   proc_info *pinfo;
00453   int i = 0, num_proc;
00454   pthread_t thread_id;
00455 
00459   /* what node do you want? */
00460   num_proc = reginfo->rootoid[reginfo->rootoid_len - 2];
00461 
00462   for(info = register_info_list; info; info = info->next)
00463     if(info->type == PROC && info->function_info.proc->num == num_proc)
00464       break;
00465 
00466   if(!info)
00467     {                           /* not found */
00468       netsnmp_request_set_error(requests, SNMP_ERR_GENERR);
00469       return SNMP_ERR_GENERR;
00470     }
00471   pinfo = info->function_info.proc;
00472   switch (reqinfo->mode)
00473     {
00474     case MODE_GET:
00475       snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
00476                                (u_char *) & (pinfo->trigger), sizeof(pinfo->trigger));
00477       break;
00478     case MODE_SET_ACTION:
00479       switch (pinfo->trigger)
00480         {
00481         case SNMP_ADM_READY:
00482           /* call the proc */
00483           pthread_create(&thread_id, NULL, launch_proc, pinfo);
00484           break;
00485         case SNMP_ADM_PROGRESS:
00486           netsnmp_request_set_error(requests, SNMP_ERR_GENERR);
00487           return SNMP_ERR_GENERR;
00488         case SNMP_ADM_DONE:
00489         case SNMP_ADM_ERROR:
00490           if((*requests->requestvb->val.integer) == 0)
00491             {
00492               /* raz */
00493               for(i = 0; i < pinfo->nb_in; i++)
00494                 memset(pinfo->inputs[i], 0, sizeof(snmp_adm_type_union));
00495 
00496               for(i = 0; i < pinfo->nb_out; i++)
00497                 memset(pinfo->outputs[i], 0, sizeof(snmp_adm_type_union));
00498 
00499               pinfo->trigger = SNMP_ADM_READY;
00500             }
00501           break;
00502         }
00503     }
00504   return SNMP_ERR_NOERROR;
00505 }