nfs-ganesha 1.4
|
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 }