void api_set_api_errnum_by_bad_response (ipmi_ctx_t ctx, fiid_obj_t obj_cmd_rs) { assert (ctx && ctx->magic == IPMI_CTX_MAGIC); /* IPMI_COMP_CODE_COMMAND_TIMEOUT, assumes it's a IPMB or command * specific timeout, so set to "MESSAGE_TIMEOUT" so user can * continue on if they wish. At minimum, returned by openipmi * driver for (what seems to be) collection of potential errors. */ if (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_COMMAND_TIMEOUT) == 1) ctx->errnum = IPMI_ERR_MESSAGE_TIMEOUT; else if (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_NODE_BUSY) == 1 || ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_OUT_OF_SPACE) == 1 || ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_SDR_REPOSITORY_IN_UPDATE_MODE) == 1 || ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_DEVICE_IN_FIRMWARE_UPDATE_MODE) == 1 || ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_BMC_INITIALIZATION_IN_PROGRESS) == 1) ctx->errnum = IPMI_ERR_BMC_BUSY; else if (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_INSUFFICIENT_PRIVILEGE_LEVEL) == 1) ctx->errnum = IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT; else if (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_INVALID_COMMAND) == 1 || ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_COMMAND_INVALID_FOR_LUN) == 1 || ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_REQUEST_DATA_LENGTH_INVALID) == 1 || ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_REQUEST_DATA_LENGTH_LIMIT_EXCEEDED) == 1 || ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_PARAMETER_OUT_OF_RANGE) == 1 || ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_INVALID_DATA_FIELD_IN_REQUEST) == 1) ctx->errnum = IPMI_ERR_COMMAND_INVALID_OR_UNSUPPORTED; else ctx->errnum = IPMI_ERR_BAD_COMPLETION_CODE; }
int ipmi_oem_get_system_info_string (ipmi_oem_state_data_t *state_data, uint8_t parameter_selector, uint8_t set_selector, uint8_t block_selector, char *string, unsigned int string_len, unsigned int *string_len_ret) { fiid_obj_t obj_cmd_rs = NULL; uint8_t configuration_parameter_data[IPMI_OEM_MAX_BYTES]; int len; int rv = -1; assert (state_data); assert (string); assert (string_len); if (!(obj_cmd_rs = fiid_obj_create (tmpl_cmd_get_system_info_parameters_rs))) { pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_create: %s\n", strerror (errno)); goto cleanup; } if (ipmi_cmd_get_system_info_parameters (state_data->ipmi_ctx, IPMI_GET_SYSTEM_INFO_PARAMETER, parameter_selector, set_selector, block_selector, obj_cmd_rs) < 0) { if ((ipmi_ctx_errnum (state_data->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE && ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_GET_SYSTEM_INFO_PARAMETERS_PARAMETER_NOT_SUPPORTED) == 1) || (ipmi_ctx_errnum (state_data->ipmi_ctx) == IPMI_ERR_COMMAND_INVALID_OR_UNSUPPORTED && ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_INVALID_DATA_FIELD_IN_REQUEST) == 1)) { pstdout_fprintf (state_data->pstate, stderr, "%s:%s '%s' option not supported on this system\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[0]); goto cleanup; } pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_get_system_info_parameters: %s\n", ipmi_ctx_errormsg (state_data->ipmi_ctx)); goto cleanup; } if ((len = fiid_obj_get_data (obj_cmd_rs, "configuration_parameter_data", configuration_parameter_data, IPMI_OEM_MAX_BYTES)) < 0) { pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_get_data: 'configuration_parameter_data': %s\n", fiid_obj_errormsg (obj_cmd_rs)); goto cleanup; } if (len > string_len) { pstdout_fprintf (state_data->pstate, stderr, "buffer overflow\n"); goto cleanup; } memcpy (string, &(configuration_parameter_data[0]), len); if (string_len_ret) (*string_len_ret) = len; rv = 0; cleanup: fiid_obj_destroy (obj_cmd_rs); return (rv); }
int ipmi_check_completion_code_success (fiid_obj_t obj_cmd) { return (ipmi_check_completion_code (obj_cmd, IPMI_COMP_CODE_COMMAND_SUCCESS)); }
static config_err_t _set_alert_policy_table (struct pef_config_state_data *state_data, const char *section_name, struct alert_policy_table *apt) { fiid_obj_t obj_cmd_rs = NULL; config_err_t rv = CONFIG_ERR_FATAL_ERROR; uint8_t alert_policy_entry_number; assert(state_data); assert(section_name); assert(apt); alert_policy_entry_number = atoi (section_name + strlen ("Alert_Policy_")); _FIID_OBJ_CREATE(obj_cmd_rs, tmpl_cmd_set_pef_configuration_parameters_rs); if (ipmi_cmd_set_pef_configuration_parameters_alert_policy_table (state_data->ipmi_ctx, alert_policy_entry_number, apt->policy_type, apt->policy_enabled, apt->policy_number, apt->destination_selector, apt->channel_number, apt->alert_string_set_selector, apt->event_specific_alert_string, obj_cmd_rs) < 0) { if (state_data->prog_data->args->config_args.common.debug) pstdout_fprintf(state_data->pstate, stderr, "ipmi_cmd_set_pef_configuration_parameters_alert_policy_table: %s\n", ipmi_ctx_strerror(ipmi_ctx_errnum(state_data->ipmi_ctx))); /* IPMI Workaround * * Fujitsu RX 100 S5 * * All fields have to be applied simultaneously, the motherboard * does not appear to like configuration of one field of a time, * always leading to invalid input errors. */ if (ipmi_ctx_errnum (state_data->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE_REQUEST_DATA_INVALID && (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_REQUEST_INVALID_DATA_FIELD) == 1)) { struct config_section *section = NULL; struct config_keyvalue *kv; unsigned int i; for (i = 0; i < state_data->alert_policy_sections_len; i++) { if (!strcasecmp (section_name, state_data->alert_policy_sections[i]->section_name)) { section = state_data->alert_policy_sections[i]; break; } } /* shouldn't be possible */ if (!section) goto cleanup; if ((kv = config_find_keyvalue (state_data->pstate, section, "Policy_Type"))) apt->policy_type = policy_type_number (kv->value_input); if ((kv = config_find_keyvalue (state_data->pstate, section, "Policy_Enabled"))) apt->policy_enabled = same (kv->value_input, "yes"); if ((kv = config_find_keyvalue (state_data->pstate, section, "Policy_Number"))) apt->policy_number = atoi (kv->value_input); if ((kv = config_find_keyvalue (state_data->pstate, section, "Destination_Selector"))) apt->destination_selector = atoi (kv->value_input); if ((kv = config_find_keyvalue (state_data->pstate, section, "Channel_Number"))) apt->channel_number = atoi (kv->value_input); if ((kv = config_find_keyvalue (state_data->pstate, section, "Alert_String_Set_Selector"))) apt->alert_string_set_selector = atoi (kv->value_input); if ((kv = config_find_keyvalue (state_data->pstate, section, "Event_Specific_Alert_String"))) apt->event_specific_alert_string = same (kv->value_input, "yes"); if (state_data->prog_data->args->config_args.common.debug) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_set_pef_configuration_parameters_alert_policy_table: attempting workaround\n"); if (ipmi_cmd_set_pef_configuration_parameters_alert_policy_table (state_data->ipmi_ctx, alert_policy_entry_number, apt->policy_type, apt->policy_enabled, apt->policy_number, apt->destination_selector, apt->channel_number, apt->alert_string_set_selector, apt->event_specific_alert_string, obj_cmd_rs) < 0) { if (state_data->prog_data->args->config_args.common.debug) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_set_pef_configuration_parameters_alert_policy_table: %s\n", ipmi_ctx_strerror(ipmi_ctx_errnum(state_data->ipmi_ctx))); if (!IPMI_CTX_ERRNUM_IS_FATAL_ERROR(state_data->ipmi_ctx)) rv = CONFIG_ERR_NON_FATAL_ERROR; goto cleanup; } /* success */ goto out; } else if (!IPMI_CTX_ERRNUM_IS_FATAL_ERROR(state_data->ipmi_ctx)) rv = CONFIG_ERR_NON_FATAL_ERROR; goto cleanup; } out: rv = CONFIG_ERR_SUCCESS; cleanup: _FIID_OBJ_DESTROY(obj_cmd_rs); return (rv); }
static config_err_t _set_authentication_type_enables (bmc_config_state_data_t *state_data, const char *section_name, struct bmc_authentication_level *al) { fiid_obj_t obj_cmd_rs = NULL; config_err_t rv = CONFIG_ERR_FATAL_ERROR; config_err_t ret; uint8_t channel_number; assert (state_data); assert (section_name); assert (al); if (!(obj_cmd_rs = fiid_obj_create (tmpl_cmd_set_lan_configuration_parameters_rs))) { pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_create: %s\n", strerror (errno)); goto cleanup; } if ((ret = get_lan_channel_number (state_data, section_name, &channel_number)) != CONFIG_ERR_SUCCESS) { rv = ret; goto cleanup; } if (ipmi_cmd_set_lan_configuration_parameters_authentication_type_enables (state_data->ipmi_ctx, channel_number, al->callback_level_none, al->callback_level_md2, al->callback_level_md5, al->callback_level_straight_password, al->callback_level_oem_proprietary, al->user_level_none, al->user_level_md2, al->user_level_md5, al->user_level_straight_password, al->user_level_oem_proprietary, al->operator_level_none, al->operator_level_md2, al->operator_level_md5, al->operator_level_straight_password, al->operator_level_oem_proprietary, al->admin_level_none, al->admin_level_md2, al->admin_level_md5, al->admin_level_straight_password, al->admin_level_oem_proprietary, al->oem_level_none, al->oem_level_md2, al->oem_level_md5, al->oem_level_straight_password, al->oem_level_oem_proprietary, obj_cmd_rs) < 0) { if (state_data->prog_data->args->config_args.common_args.debug) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_set_lan_configuration_parameters_authentication_type_enables: %s\n", ipmi_ctx_errormsg (state_data->ipmi_ctx)); /* * IPMI Workaround * * Dell Poweredge R610 * * Nodes come default w/ OEM authentication enables turned * on, but you cannot configure them on. So this always * leads to invalid data errors (0xCC) b/c we are * configuring one field at a time. So we will "absorb" the * OEM configuration of later fields and try again, hoping * that the user has tried to "right" the badness already * sitting on the motherboard. */ if (ipmi_ctx_errnum (state_data->ipmi_ctx) == IPMI_ERR_COMMAND_INVALID_OR_UNSUPPORTED && (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_INVALID_DATA_FIELD_IN_REQUEST) == 1)) { struct config_section *section; struct config_keyvalue *kv; section = state_data->sections; while (section) { if (!strcasecmp (section->section_name, "Lan_Conf_Auth")) break; section = section->next; } /* shouldn't be possible */ if (!section) goto cleanup; if ((kv = config_find_keyvalue (section, "Callback_Enable_Auth_Type_OEM_Proprietary"))) al->callback_level_oem_proprietary = same (kv->value_input, "yes"); if ((kv = config_find_keyvalue (section, "User_Enable_Auth_Type_OEM_Proprietary"))) al->user_level_oem_proprietary = same (kv->value_input, "yes"); if ((kv = config_find_keyvalue (section, "Operator_Enable_Auth_Type_OEM_Proprietary"))) al->operator_level_oem_proprietary = same (kv->value_input, "yes"); if ((kv = config_find_keyvalue (section, "Admin_Enable_Auth_Type_OEM_Proprietary"))) al->admin_level_oem_proprietary = same (kv->value_input, "yes"); if ((kv = config_find_keyvalue (section, "OEM_Enable_Auth_Type_None"))) al->oem_level_none = same (kv->value_input, "yes"); if ((kv = config_find_keyvalue (section, "OEM_Enable_Auth_Type_MD2"))) al->oem_level_md2 = same (kv->value_input, "yes"); if ((kv = config_find_keyvalue (section, "OEM_Enable_Auth_Type_MD5"))) al->oem_level_md5 = same (kv->value_input, "yes"); if ((kv = config_find_keyvalue (section, "OEM_Enable_Auth_Type_Straight_Password"))) al->oem_level_straight_password = same (kv->value_input, "yes"); if ((kv = config_find_keyvalue (section, "OEM_Enable_Auth_Type_OEM_Proprietary"))) al->oem_level_oem_proprietary = same (kv->value_input, "yes"); if (ipmi_cmd_set_lan_configuration_parameters_authentication_type_enables (state_data->ipmi_ctx, channel_number, al->callback_level_none, al->callback_level_md2, al->callback_level_md5, al->callback_level_straight_password, al->callback_level_oem_proprietary, al->user_level_none, al->user_level_md2, al->user_level_md5, al->user_level_straight_password, al->user_level_oem_proprietary, al->operator_level_none, al->operator_level_md2, al->operator_level_md5, al->operator_level_straight_password, al->operator_level_oem_proprietary, al->admin_level_none, al->admin_level_md2, al->admin_level_md5, al->admin_level_straight_password, al->admin_level_oem_proprietary, al->oem_level_none, al->oem_level_md2, al->oem_level_md5, al->oem_level_straight_password, al->oem_level_oem_proprietary, obj_cmd_rs) < 0) { if (state_data->prog_data->args->config_args.common_args.debug) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_set_lan_configuration_parameters_authentication_type_enables: %s\n", ipmi_ctx_errormsg (state_data->ipmi_ctx)); if (config_is_config_param_non_fatal_error (state_data->ipmi_ctx, obj_cmd_rs, &ret)) rv = ret; goto cleanup; } /* success!! */ goto out; } else if (config_is_config_param_non_fatal_error (state_data->ipmi_ctx, obj_cmd_rs, &ret)) rv = ret; goto cleanup; } out: rv = CONFIG_ERR_SUCCESS; cleanup: fiid_obj_destroy (obj_cmd_rs); return (rv); }
static config_err_t _set_alert_policy_table (struct ipmi_pef_config_state_data *state_data, const char *section_name, struct alert_policy_table *apt) { fiid_obj_t obj_cmd_rs = NULL; config_err_t rv = CONFIG_ERR_FATAL_ERROR; uint8_t alert_policy_entry_number; assert (state_data); assert (section_name); assert (apt); alert_policy_entry_number = atoi (section_name + strlen ("Alert_Policy_")); if (!(obj_cmd_rs = fiid_obj_create (tmpl_cmd_set_pef_configuration_parameters_rs))) { pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_create: %s\n", strerror (errno)); goto cleanup; } if (ipmi_cmd_set_pef_configuration_parameters_alert_policy_table (state_data->ipmi_ctx, alert_policy_entry_number, apt->policy_type, apt->policy_enabled, apt->policy_number, apt->destination_selector, apt->channel_number, apt->alert_string_set_selector, apt->event_specific_alert_string, obj_cmd_rs) < 0) { config_err_t ret; if (state_data->prog_data->args->config_args.common_args.debug) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_set_pef_configuration_parameters_alert_policy_table: %s\n", ipmi_ctx_errormsg (state_data->ipmi_ctx)); /* IPMI Workaround * * Fujitsu RX 100 S5 * * Inventec 5441/Dell Xanadu II * * All fields have to be applied simultaneously, the motherboard * does not appear to like configuration of one field of a time, * always leading to invalid input errors. This isn't a * compliance issue, but makes it tough to make a portable/good * interface. */ if (ipmi_ctx_errnum (state_data->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE && (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_INVALID_DATA_FIELD_IN_REQUEST) == 1)) { struct config_section *section; struct config_keyvalue *kv; section = state_data->sections; while (section) { if (!strcasecmp (section_name, section->section_name)) break; section = section->next; } /* shouldn't be possible */ if (!section) goto cleanup; if ((kv = config_find_keyvalue (section, "Policy_Type"))) apt->policy_type = policy_type_number (kv->value_input); if ((kv = config_find_keyvalue (section, "Policy_Enabled"))) apt->policy_enabled = same (kv->value_input, "yes"); if ((kv = config_find_keyvalue (section, "Policy_Number"))) apt->policy_number = atoi (kv->value_input); if ((kv = config_find_keyvalue (section, "Destination_Selector"))) apt->destination_selector = atoi (kv->value_input); if ((kv = config_find_keyvalue (section, "Channel_Number"))) apt->channel_number = atoi (kv->value_input); if ((kv = config_find_keyvalue (section, "Alert_String_Set_Selector"))) apt->alert_string_set_selector = atoi (kv->value_input); if ((kv = config_find_keyvalue (section, "Event_Specific_Alert_String"))) apt->event_specific_alert_string = same (kv->value_input, "yes"); if (state_data->prog_data->args->config_args.common_args.debug) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_set_pef_configuration_parameters_alert_policy_table: attempting workaround\n"); if (ipmi_cmd_set_pef_configuration_parameters_alert_policy_table (state_data->ipmi_ctx, alert_policy_entry_number, apt->policy_type, apt->policy_enabled, apt->policy_number, apt->destination_selector, apt->channel_number, apt->alert_string_set_selector, apt->event_specific_alert_string, obj_cmd_rs) < 0) { if (state_data->prog_data->args->config_args.common_args.debug) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_set_pef_configuration_parameters_alert_policy_table: %s\n", ipmi_ctx_errormsg (state_data->ipmi_ctx)); if (config_is_config_param_non_fatal_error (state_data->ipmi_ctx, obj_cmd_rs, &ret)) rv = ret; goto cleanup; } /* success */ goto out; } else if (config_is_config_param_non_fatal_error (state_data->ipmi_ctx, obj_cmd_rs, &ret)) rv = ret; goto cleanup; } out: rv = CONFIG_ERR_SUCCESS; cleanup: fiid_obj_destroy (obj_cmd_rs); return (rv); }
static int _api_ssif_ipmb_send (ipmi_ctx_t ctx, fiid_obj_t obj_cmd_rq) { struct ipmi_ctx_target target_save; uint8_t buf[IPMI_MAX_PKT_LEN]; fiid_obj_t obj_ipmb_msg_hdr_rq = NULL; fiid_obj_t obj_ipmb_msg_rq = NULL; fiid_obj_t obj_send_cmd_rs = NULL; int len, ret, rv = -1; assert (ctx && ctx->magic == IPMI_CTX_MAGIC && ctx->type == IPMI_DEVICE_SSIF && fiid_obj_valid (obj_cmd_rq) && fiid_obj_packet_valid (obj_cmd_rq) == 1); if (!(obj_ipmb_msg_hdr_rq = fiid_obj_create (tmpl_ipmb_msg_hdr_rq))) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if (!(obj_ipmb_msg_rq = fiid_obj_create (tmpl_ipmb_msg))) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if (!(obj_send_cmd_rs = fiid_obj_create (tmpl_cmd_send_message_rs))) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if (fill_ipmb_msg_hdr (ctx->target.rs_addr, ctx->target.net_fn, ctx->target.lun, IPMI_SLAVE_ADDRESS_BMC, IPMI_BMC_IPMB_LUN_SMS_MSG_LUN, ctx->io.inband.rq_seq, obj_ipmb_msg_hdr_rq) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if (assemble_ipmi_ipmb_msg (obj_ipmb_msg_hdr_rq, obj_cmd_rq, obj_ipmb_msg_rq, IPMI_INTERFACE_FLAGS_DEFAULT) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } memset (buf, '\0', IPMI_MAX_PKT_LEN); if ((len = fiid_obj_get_all (obj_ipmb_msg_rq, buf, IPMI_MAX_PKT_LEN)) < 0) { API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_ipmb_msg_rq); goto cleanup; } /* send_message will send to the BMC, so clear out target information */ memcpy (&target_save, &ctx->target, sizeof (target_save)); ctx->target.channel_number_is_set = 0; ctx->target.rs_addr_is_set = 0; ret = ipmi_cmd_send_message (ctx, target_save.channel_number, IPMI_SEND_MESSAGE_AUTHENTICATION_NOT_REQUIRED, IPMI_SEND_MESSAGE_ENCRYPTION_NOT_REQUIRED, IPMI_SEND_MESSAGE_TRACKING_OPERATION_NO_TRACKING, buf, len, obj_send_cmd_rs); /* restore target info */ memcpy (&ctx->target, &target_save, sizeof (target_save)); if (ret < 0) { /* assume these mean can't send message, bad slave address, etc. */ if (ipmi_check_completion_code (obj_send_cmd_rs, IPMI_COMP_CODE_SEND_MESSAGE_LOST_ARBITRATION) == 1 || ipmi_check_completion_code (obj_send_cmd_rs, IPMI_COMP_CODE_SEND_MESSAGE_BUS_ERROR) == 1 || ipmi_check_completion_code (obj_send_cmd_rs, IPMI_COMP_CODE_SEND_MESSAGE_NAK_ON_WRITE) == 1) API_SET_ERRNUM (ctx, IPMI_ERR_MESSAGE_TIMEOUT); else API_BAD_RESPONSE_TO_API_ERRNUM (ctx, obj_send_cmd_rs); goto cleanup; } rv = 0; cleanup: fiid_obj_destroy (obj_ipmb_msg_hdr_rq); fiid_obj_destroy (obj_ipmb_msg_rq); fiid_obj_destroy (obj_send_cmd_rs); return (rv); }
static int _api_ssif_ipmb_recv (ipmi_ctx_t ctx, fiid_obj_t obj_ipmb_msg_hdr_rs, fiid_obj_t obj_ipmb_msg_trlr, fiid_obj_t obj_cmd_rs) { struct ipmi_ctx_target target_save; uint8_t buf[IPMI_MAX_PKT_LEN]; fiid_obj_t obj_ipmb_msg_rs = NULL; fiid_obj_t obj_get_cmd_rs = NULL; int len, ret, rv = -1; unsigned int intf_flags = IPMI_INTERFACE_FLAGS_DEFAULT; assert (ctx && ctx->magic == IPMI_CTX_MAGIC && ctx->type == IPMI_DEVICE_SSIF && fiid_obj_valid (obj_ipmb_msg_hdr_rs) && fiid_obj_valid (obj_ipmb_msg_trlr) && fiid_obj_valid (obj_cmd_rs)); if (ctx->flags & IPMI_FLAGS_NO_LEGAL_CHECK) intf_flags |= IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK; if (!(obj_ipmb_msg_rs = fiid_obj_create (tmpl_ipmb_msg))) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } if (!(obj_get_cmd_rs = fiid_obj_create (tmpl_cmd_get_message_rs))) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } /* get_message will send to the BMC, so clear out target information */ memcpy (&target_save, &ctx->target, sizeof (target_save)); ctx->target.channel_number_is_set = 0; ctx->target.rs_addr_is_set = 0; ret = ipmi_cmd_get_message (ctx, obj_get_cmd_rs); /* restore target info */ memcpy (&ctx->target, &target_save, sizeof (target_save)); if (ret < 0) { if (ipmi_check_completion_code (obj_get_cmd_rs, IPMI_COMP_CODE_GET_MESSAGE_DATA_NOT_AVAILABLE) == 1) API_SET_ERRNUM (ctx, IPMI_ERR_MESSAGE_TIMEOUT); else API_BAD_RESPONSE_TO_API_ERRNUM (ctx, obj_get_cmd_rs); goto cleanup; } if ((len = fiid_obj_get_data (obj_get_cmd_rs, "message_data", buf, IPMI_MAX_PKT_LEN)) < 0) { API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_get_cmd_rs); goto cleanup; } if (fiid_obj_set_all (obj_ipmb_msg_rs, buf, len) < 0) { API_FIID_OBJECT_ERROR_TO_API_ERRNUM (ctx, obj_ipmb_msg_rs); goto cleanup; } if (unassemble_ipmi_ipmb_msg (obj_ipmb_msg_rs, obj_ipmb_msg_hdr_rs, obj_cmd_rs, obj_ipmb_msg_trlr, intf_flags) < 0) { API_ERRNO_TO_API_ERRNUM (ctx, errno); goto cleanup; } rv = 0; cleanup: fiid_obj_destroy (obj_ipmb_msg_rs); fiid_obj_destroy (obj_get_cmd_rs); return (rv); }
static ipmi_config_err_t _set_power_limit (ipmi_config_state_data_t *state_data, const char *section_name, struct get_power_limit_data *gpld, int no_set_power_limit_flag) { fiid_obj_t obj_cmd_rs = NULL; ipmi_config_err_t rv = IPMI_CONFIG_ERR_FATAL_ERROR; assert (state_data); assert (section_name); assert (gpld); /* IPMI Workaround/Interpretation * * The DCMI spec indicates a potential completion code for the * "Get Power Limit" command as "No Set Power Limit" (0x80). * FreeIPMI originally interpreted this to mean the "Set Power * Limit" command was not available. Atleast one vendor * interpreted this to mean "No Power Limit Set". One can * consider this an English interpretation issue of 'No set * POWER LIMIT' vs. 'No SET POWER LIMIT' (i.e. is "set" a verb * or part of a proper noun referencing the DCMI command). * Confounding this issue is the fact that the example * implementation in Intel's DCMItool implements the former, * while the DCMI Conformance test suite implements the latter. * In addition to this, with the latter interpretation, it need * not be an indication of an error, but rather a flag. So the * rest of the packet can be completely full of legitimate data. * * So we will do the following. * * If the "No Set Power Limit" completion code is returned and * we were able to read all of the fields, _get_power_limit() will * return normally, so we don't need to worry about this case. * * If the "No Set Power Limit", completion code is returned and * we were *not* able to read all of the fields, we won't have * values from "Get Power Limit" and won't know how to do the * configuration properly in "Set Power Limit". So we will * require that the user input all fields for "Set Power Limit". */ if (no_set_power_limit_flag) { struct ipmi_config_section *section; struct ipmi_config_keyvalue *kv; section = state_data->sections; while (section) { if (!strcasecmp (section_name, section->section_name)) break; section = section->next; } /* shouldn't be possible */ if (!section) goto cleanup; if ((kv = ipmi_config_find_keyvalue (section, "Policy_Type"))) gpld->power_limit_requested = atoi (kv->value_input); if ((kv = ipmi_config_find_keyvalue (section, "Policy_Enabled"))) gpld->correction_time_limit = strtoul (kv->value_input, NULL, 0); if ((kv = ipmi_config_find_keyvalue (section, "Management_Application_Statistics_Sampling_Period"))) gpld->management_application_statistics_sampling_period = atoi (kv->value_input); if ((kv = ipmi_config_find_keyvalue (section, "Exception_Actions"))) { int num = exception_actions_number (kv->value_input); if (num < 0) /* previously checked for correctness, so no error check */ gpld->exception_actions = strtol (kv->value_input, NULL, 0); else gpld->exception_actions = num; } } if (!(obj_cmd_rs = fiid_obj_create (tmpl_cmd_dcmi_set_power_limit_rs))) { pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_create: %s\n", strerror (errno)); goto cleanup; } if (ipmi_cmd_dcmi_set_power_limit (state_data->ipmi_ctx, gpld->exception_actions, gpld->power_limit_requested, gpld->correction_time_limit, gpld->management_application_statistics_sampling_period, obj_cmd_rs) < 0) { ipmi_config_err_t ret; if ((ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_DCMI_POWER_LIMIT_OUT_OF_RANGE) == 1) || (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_DCMI_CORRECTION_TIME_OUT_OF_RANGE) == 1) || (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_DCMI_STATISTICS_REPORTING_PERIOD_OUT_OF_RANGE) == 1)) rv = IPMI_CONFIG_ERR_NON_FATAL_ERROR; else { if (ipmi_config_param_errnum_is_non_fatal (state_data, obj_cmd_rs, &ret)) rv = ret; } if (rv == IPMI_CONFIG_ERR_FATAL_ERROR || state_data->prog_data->args->common_args.debug) { if (ipmi_ctx_errnum (state_data->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE && ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_DCMI_POWER_LIMIT_OUT_OF_RANGE) == 1) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_dcmi_set_power_limit: %s\n", IPMI_COMP_CODE_DCMI_POWER_LIMIT_OUT_OF_RANGE_STR); else if (ipmi_ctx_errnum (state_data->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE && ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_DCMI_CORRECTION_TIME_OUT_OF_RANGE) == 1) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_dcmi_set_power_limit: %s\n", IPMI_COMP_CODE_DCMI_CORRECTION_TIME_OUT_OF_RANGE_STR); else if (ipmi_ctx_errnum (state_data->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE && ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_DCMI_STATISTICS_REPORTING_PERIOD_OUT_OF_RANGE) == 1) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_dcmi_set_power_limit: %s\n", IPMI_COMP_CODE_DCMI_STATISTICS_REPORTING_PERIOD_OUT_OF_RANGE_STR); else pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_dcmi_set_power_limit: %s\n", ipmi_ctx_errormsg (state_data->ipmi_ctx)); } goto cleanup; } rv = IPMI_CONFIG_ERR_SUCCESS; cleanup: fiid_obj_destroy (obj_cmd_rs); return (rv); }
static ipmi_config_err_t _get_power_limit (ipmi_config_state_data_t *state_data, struct get_power_limit_data *gpld, int *no_set_power_limit_flag) { fiid_obj_t obj_cmd_rs = NULL; uint64_t val; int no_set_power_limit_error_flag = 0; ipmi_config_err_t rv = IPMI_CONFIG_ERR_FATAL_ERROR; assert (state_data); assert (gpld); if (no_set_power_limit_flag) (*no_set_power_limit_flag) = 0; if (!(obj_cmd_rs = fiid_obj_create (tmpl_cmd_dcmi_get_power_limit_rs))) { pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_create: %s", strerror (errno)); goto cleanup; } /* IPMI Workaround/Interpretation * * The DCMI spec indicates a potential completion code for the "Get * Power Limit" command as "No Set Power Limit" (0x80). FreeIPMI * originally interpreted this to mean the "Set Power Limit" command * was not available. Atleast one vendor interpreted this to mean * "No Power Limit Set". One can consider this an English * interpretation issue of 'No set POWER LIMIT' vs. 'No SET POWER * LIMIT' (i.e. is "set" a verb or part of a proper noun referencing * the DCMI command). Confounding this issue is the fact that the * example implementation in Intel's DCMItool implements the former, * while the DCMI Conformance test suite implements the latter. In * addition to this, with the latter interpretation, it need not be * an indication of an error, but rather a flag. So the rest of the * packet can be completely full of legitimate data. * * So how do we handle this? * * If we hit "No Set Power Limit", try to read data. If we can't * read data (b/c it's not set), fail out, but preserve the "No Set * Power Limit" error message. */ if (ipmi_cmd_dcmi_get_power_limit (state_data->ipmi_ctx, obj_cmd_rs) < 0) { ipmi_config_err_t ret; if (ipmi_ctx_errnum (state_data->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE && ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_DCMI_NO_SET_POWER_LIMIT) == 1) { if (state_data->prog_data->args->common_args.debug) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_dcmi_get_power_limit: %s", IPMI_COMP_CODE_DCMI_NO_SET_POWER_LIMIT_STR); if (no_set_power_limit_flag) (*no_set_power_limit_flag) = 1; no_set_power_limit_error_flag++; goto read_data; } if (ipmi_config_param_errnum_is_non_fatal (state_data, obj_cmd_rs, &ret)) rv = ret; if (rv == IPMI_CONFIG_ERR_FATAL_ERROR || state_data->prog_data->args->common_args.debug) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_get_pef_configuration_parameters_event_filter_table: %s\n", ipmi_ctx_errormsg (state_data->ipmi_ctx)); goto cleanup; } read_data: if (FIID_OBJ_GET (obj_cmd_rs, "exception_actions", &val) < 0) { if (!no_set_power_limit_error_flag || fiid_obj_errnum (obj_cmd_rs) != FIID_ERR_DATA_NOT_AVAILABLE) pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_get: 'exception_actions': %s", fiid_obj_errormsg (obj_cmd_rs)); if (no_set_power_limit_error_flag) rv = IPMI_CONFIG_ERR_NON_FATAL_ERROR; goto cleanup; } gpld->exception_actions = val; if (FIID_OBJ_GET (obj_cmd_rs, "power_limit_requested", &val) < 0) { if (!no_set_power_limit_error_flag || fiid_obj_errnum (obj_cmd_rs) != FIID_ERR_DATA_NOT_AVAILABLE) pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_get: 'power_limit_requested': %s", fiid_obj_errormsg (obj_cmd_rs)); if (no_set_power_limit_error_flag) rv = IPMI_CONFIG_ERR_NON_FATAL_ERROR; goto cleanup; } gpld->power_limit_requested = val; if (FIID_OBJ_GET (obj_cmd_rs, "correction_time_limit", &val) < 0) { if (!no_set_power_limit_error_flag || fiid_obj_errnum (obj_cmd_rs) != FIID_ERR_DATA_NOT_AVAILABLE) pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_get: 'correction_time_limit': %s", fiid_obj_errormsg (obj_cmd_rs)); if (no_set_power_limit_error_flag) rv = IPMI_CONFIG_ERR_NON_FATAL_ERROR; goto cleanup; } gpld->correction_time_limit = val; if (FIID_OBJ_GET (obj_cmd_rs, "management_application_statistics_sampling_period", &val) < 0) { if (!no_set_power_limit_error_flag || fiid_obj_errnum (obj_cmd_rs) != FIID_ERR_DATA_NOT_AVAILABLE) pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_get: 'management_application_statistics_sampling_period': %s", fiid_obj_errormsg (obj_cmd_rs)); if (no_set_power_limit_error_flag) rv = IPMI_CONFIG_ERR_NON_FATAL_ERROR; goto cleanup; } gpld->management_application_statistics_sampling_period = val; rv = IPMI_CONFIG_ERR_SUCCESS; cleanup: fiid_obj_destroy (obj_cmd_rs); return (rv); }
int ipmi_sensors_get_thresholds (ipmi_sensors_state_data_t *state_data, uint8_t *sdr_record, unsigned int sdr_record_len, double **lower_non_critical_threshold, double **lower_critical_threshold, double **lower_non_recoverable_threshold, double **upper_non_critical_threshold, double **upper_critical_threshold, double **upper_non_recoverable_threshold) { int8_t r_exponent, b_exponent; int16_t m, b; uint8_t linearization, analog_data_format; uint8_t sensor_number; fiid_obj_t obj_cmd_rs = NULL; double *tmp_lower_non_critical_threshold = NULL; double *tmp_lower_critical_threshold = NULL; double *tmp_lower_non_recoverable_threshold = NULL; double *tmp_upper_non_critical_threshold = NULL; double *tmp_upper_critical_threshold = NULL; double *tmp_upper_non_recoverable_threshold = NULL; double threshold; uint8_t threshold_access_support; uint64_t val; int rv = -1; assert(state_data); assert(sdr_record); assert(sdr_record_len); if (lower_non_critical_threshold) *lower_non_critical_threshold = NULL; if (lower_critical_threshold) *lower_critical_threshold = NULL; if (lower_non_recoverable_threshold) *lower_non_recoverable_threshold = NULL; if (upper_non_critical_threshold) *upper_non_critical_threshold = NULL; if (upper_critical_threshold) *upper_critical_threshold = NULL; if (upper_non_recoverable_threshold) *upper_non_recoverable_threshold = NULL; /* achu: first lets check if we have anything to output */ if (sdr_cache_get_sensor_capabilities (state_data->pstate, sdr_record, sdr_record_len, NULL, &threshold_access_support, NULL, NULL, NULL) < 0) goto cleanup; if (threshold_access_support == IPMI_SDR_NO_THRESHOLDS_SUPPORT || threshold_access_support == IPMI_SDR_FIXED_UNREADABLE_THRESHOLDS_SUPPORT) { rv = 0; goto cleanup; } /* achu: * * I will admit I'm not entirely sure what the best way is * to get thresholds. It seems the information is * stored/retrievable in the SDR and through an IPMI command. * * Since the readable_threshold_mask in the SDR record indicates the * mask is for the "Get Sensor Thresholds" command, it suggests the * best/right way is to get the values via that command. Sounds * good to me. Also, I suppose its possible that changes to the * thresholds may not be written to the SDR. * * Also, because the results from the get_sensor_thresholds include * readability flags, we can ignore the readability flags in the * SDR. * */ if (sdr_cache_get_sensor_number (state_data->pstate, sdr_record, sdr_record_len, &sensor_number) < 0) goto cleanup; if (sdr_cache_get_sensor_decoding_data(state_data->pstate, sdr_record, sdr_record_len, &r_exponent, &b_exponent, &m, &b, &linearization, &analog_data_format) < 0) goto cleanup; /* if the sensor is not analog, this is most likely a bug in the * SDR, since we shouldn't be decoding a non-threshold sensor. * * Don't return an error. Allow code to output "NA" or something. */ if (!IPMI_SDR_ANALOG_DATA_FORMAT_VALID(analog_data_format)) { if (state_data->prog_data->args->common.debug) pstdout_fprintf(state_data->pstate, stderr, "Attempting to decode non-analog sensor\n"); rv = 0; goto cleanup; } /* if the sensor is non-linear, I just don't know what to do * * Don't return an error. Allow code to output "NA" or something. */ if (!IPMI_SDR_LINEARIZATION_IS_LINEAR(linearization)) { if (state_data->prog_data->args->common.debug) pstdout_fprintf(state_data->pstate, stderr, "Cannot decode non-linear sensor\n"); rv = 0; goto cleanup; } _FIID_OBJ_CREATE(obj_cmd_rs, tmpl_cmd_get_sensor_thresholds_rs); if (ipmi_cmd_get_sensor_thresholds (state_data->ipmi_ctx, sensor_number, obj_cmd_rs) < 0) { if (state_data->prog_data->args->common.debug) pstdout_fprintf(state_data->pstate, stderr, "ipmi_cmd_get_sensor_thresholds: %s\n", ipmi_ctx_strerror(ipmi_ctx_errnum(state_data->ipmi_ctx))); if ((ipmi_ctx_errnum(state_data->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE_REQUEST_DATA_INVALID) && (ipmi_check_completion_code(obj_cmd_rs, IPMI_COMP_CODE_COMMAND_ILLEGAL_FOR_SENSOR_OR_RECORD_TYPE) == 1 || ipmi_check_completion_code(obj_cmd_rs, IPMI_COMP_CODE_REQUEST_SENSOR_DATA_OR_RECORD_NOT_PRESENT) == 1)) { /* The thresholds cannot be gathered for one reason or * another, maybe b/c its a OEM sensor or something. We can * return 0 gracefully. */ rv = 0; goto cleanup; } /* * IPMI Workaround (achu) * * Discovered on HP DL585 * * Seems that the HP machine doesn't support the "Get Sensor * Thresholds" command. When this occurs, we assume the * information in the SDR is legit and up to date. Go get it * and fill in the object respectively. */ if ((ipmi_ctx_errnum(state_data->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE_INVALID_COMMAND) && (ipmi_check_completion_code(obj_cmd_rs, IPMI_COMP_CODE_COMMAND_INVALID) == 1)) { if (state_data->prog_data->args->common.debug) pstdout_fprintf(state_data->pstate, stderr, "Get Sensor Thresholds failed, using SDR information\n"); if (_get_sdr_sensor_thresholds (state_data, sdr_record, sdr_record_len, obj_cmd_rs) < 0) goto cleanup; goto continue_get_sensor_thresholds; } goto cleanup; } continue_get_sensor_thresholds: if (lower_non_critical_threshold) { _FIID_OBJ_GET (obj_cmd_rs, "readable_thresholds.lower_non_critical_threshold", &val); if (val) { _FIID_OBJ_GET(obj_cmd_rs, "lower_non_critical_threshold", &val); if (ipmi_sensor_decode_value (r_exponent, b_exponent, m, b, linearization, analog_data_format, val, &threshold) < 0) { pstdout_fprintf (state_data->pstate, stderr, "ipmi_sensor_decode_value: %s\n", strerror(errno)); goto cleanup; } if (!(tmp_lower_non_critical_threshold = (double *)malloc(sizeof(double)))) { pstdout_perror(state_data->pstate, "malloc"); goto cleanup; } *tmp_lower_non_critical_threshold = threshold; } } if (lower_critical_threshold) { _FIID_OBJ_GET (obj_cmd_rs, "readable_thresholds.lower_critical_threshold", &val); if (val) { _FIID_OBJ_GET(obj_cmd_rs, "lower_critical_threshold", &val); if (ipmi_sensor_decode_value (r_exponent, b_exponent, m, b, linearization, analog_data_format, val, &threshold) < 0) { pstdout_fprintf (state_data->pstate, stderr, "ipmi_sensor_decode_value: %s\n", strerror(errno)); goto cleanup; } if (!(tmp_lower_critical_threshold = (double *)malloc(sizeof(double)))) { pstdout_perror(state_data->pstate, "malloc"); goto cleanup; } *tmp_lower_critical_threshold = threshold; } } if (lower_non_recoverable_threshold) { _FIID_OBJ_GET (obj_cmd_rs, "readable_thresholds.lower_non_recoverable_threshold", &val); if (val) { _FIID_OBJ_GET(obj_cmd_rs, "lower_non_recoverable_threshold", &val); if (ipmi_sensor_decode_value (r_exponent, b_exponent, m, b, linearization, analog_data_format, val, &threshold) < 0) { pstdout_fprintf (state_data->pstate, stderr, "ipmi_sensor_decode_value: %s\n", strerror(errno)); goto cleanup; } if (!(tmp_lower_non_recoverable_threshold = (double *)malloc(sizeof(double)))) { pstdout_perror(state_data->pstate, "malloc"); goto cleanup; } *tmp_lower_non_recoverable_threshold = threshold; } } if (upper_non_critical_threshold) { _FIID_OBJ_GET (obj_cmd_rs, "readable_thresholds.upper_non_critical_threshold", &val); if (val) { _FIID_OBJ_GET(obj_cmd_rs, "upper_non_critical_threshold", &val); if (ipmi_sensor_decode_value (r_exponent, b_exponent, m, b, linearization, analog_data_format, val, &threshold) < 0) { pstdout_fprintf (state_data->pstate, stderr, "ipmi_sensor_decode_value: %s\n", strerror(errno)); goto cleanup; } if (!(tmp_upper_non_critical_threshold = (double *)malloc(sizeof(double)))) { pstdout_perror(state_data->pstate, "malloc"); goto cleanup; } *tmp_upper_non_critical_threshold = threshold; } } if (upper_critical_threshold) { _FIID_OBJ_GET (obj_cmd_rs, "readable_thresholds.upper_critical_threshold", &val); if (val) { _FIID_OBJ_GET(obj_cmd_rs, "upper_critical_threshold", &val); if (ipmi_sensor_decode_value (r_exponent, b_exponent, m, b, linearization, analog_data_format, val, &threshold) < 0) { pstdout_fprintf (state_data->pstate, stderr, "ipmi_sensor_decode_value: %s\n", strerror(errno)); goto cleanup; } if (!(tmp_upper_critical_threshold = (double *)malloc(sizeof(double)))) { pstdout_perror(state_data->pstate, "malloc"); goto cleanup; } *tmp_upper_critical_threshold = threshold; } } if (upper_non_recoverable_threshold) { _FIID_OBJ_GET (obj_cmd_rs, "readable_thresholds.upper_non_recoverable_threshold", &val); if (val) { _FIID_OBJ_GET(obj_cmd_rs, "upper_non_recoverable_threshold", &val); if (ipmi_sensor_decode_value (r_exponent, b_exponent, m, b, linearization, analog_data_format, val, &threshold) < 0) { pstdout_fprintf (state_data->pstate, stderr, "ipmi_sensor_decode_value: %s\n", strerror(errno)); goto cleanup; } if (!(tmp_upper_non_recoverable_threshold = (double *)malloc(sizeof(double)))) { pstdout_perror(state_data->pstate, "malloc"); goto cleanup; } *tmp_upper_non_recoverable_threshold = threshold; } } if (lower_non_critical_threshold) *lower_non_critical_threshold = tmp_lower_non_critical_threshold; if (lower_critical_threshold) *lower_critical_threshold = tmp_lower_critical_threshold; if (lower_non_recoverable_threshold) *lower_non_recoverable_threshold = tmp_lower_non_recoverable_threshold; if (upper_non_critical_threshold) *upper_non_critical_threshold = tmp_upper_non_critical_threshold; if (upper_critical_threshold) *upper_critical_threshold = tmp_upper_critical_threshold; if (upper_non_recoverable_threshold) *upper_non_recoverable_threshold = tmp_upper_non_recoverable_threshold; rv = 0; cleanup: _FIID_OBJ_DESTROY(obj_cmd_rs); if (rv < 0) { if (tmp_lower_non_critical_threshold) free(tmp_lower_non_critical_threshold); if (tmp_lower_critical_threshold) free(tmp_lower_critical_threshold); if (tmp_lower_non_recoverable_threshold) free(tmp_lower_non_recoverable_threshold); if (tmp_upper_non_critical_threshold) free(tmp_upper_non_critical_threshold); if (tmp_upper_critical_threshold) free(tmp_upper_critical_threshold); if (tmp_upper_non_recoverable_threshold) free(tmp_upper_non_recoverable_threshold); } return rv; }
int _sensor_reading_corner_case_checks (ipmi_sensor_read_ctx_t ctx, fiid_obj_t obj_cmd_rs) { assert (ctx); assert (ctx->magic == IPMI_SENSOR_READ_CTX_MAGIC); assert (obj_cmd_rs); if (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_NODE_BUSY) == 1) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_NODE_BUSY); return (-1); } /* IPMI Workaround * * achu: Error codes found on motherboards that strongly suggest * "sensor not available". See comments in * freeipmi-bugs-issues-and-workarounds.txt for why I think this is * a workaround and not an "ok" set of errors. */ else if ((ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_REQUESTED_SENSOR_DATA_OR_RECORD_NOT_PRESENT) == 1) || (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_COMMAND_ILLEGAL_FOR_SENSOR_OR_RECORD_TYPE) == 1) || (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_PARAMETER_OUT_OF_RANGE) == 1) || (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_INVALID_DATA_FIELD_IN_REQUEST) == 1) || (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_COMMAND_RESPONSE_COULD_NOT_BE_PROVIDED) == 1) || (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_REQUEST_PARAMETER_NOT_SUPPORTED) == 1) || (ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_DESTINATION_UNAVAILABLE) == 1)) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SENSOR_READING_UNAVAILABLE); return (-1); } else if ((ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_UNSPECIFIED_ERROR) == 1)) { uint64_t val; int flag; /* IPMI Workaround * * Discovered on Sun Blade x6250 * * For some reason, some sensors can return this error code * (0xFF). However, it appears to be an invalid error response * b/c the sensor properly reports that the sensor reading is * not available or that scanning is diabled. So if the sensor * reports that it is unavailable, we'll report an error code * slightly more appropriate. * * Note, I do not handle this identically to the corner case * checks above. Those completion codes strongly suggest that a * sensor is not available. The error code "Unspecified Error" * could mean anything. */ if ((flag = fiid_obj_get (obj_cmd_rs, "reading_state", &val)) < 0) { SENSOR_READ_FIID_OBJECT_ERROR_TO_SENSOR_READ_ERRNUM (ctx, obj_cmd_rs); return (-1); } if (flag && val == IPMI_SENSOR_READING_STATE_UNAVAILABLE) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SENSOR_READING_UNAVAILABLE); return (-1); } if (!(ctx->flags & IPMI_SENSOR_READ_FLAGS_IGNORE_SCANNING_DISABLED)) { if ((flag = fiid_obj_get (obj_cmd_rs, "sensor_scanning", &val)) < 0) { SENSOR_READ_FIID_OBJECT_ERROR_TO_SENSOR_READ_ERRNUM (ctx, obj_cmd_rs); return (-1); } if (flag && val == IPMI_SENSOR_SCANNING_ON_THIS_SENSOR_DISABLE) { SENSOR_READ_SET_ERRNUM (ctx, IPMI_SENSOR_READ_ERR_SENSOR_SCANNING_DISABLED); return (-1); } } /* else fall through like normal */ } return (0); }
static config_err_t threshold_checkout (const char *section_name, struct config_keyvalue *kv, void *arg) { ipmi_sensors_config_state_data_t *state_data; fiid_obj_t obj_cmd_rs = NULL; config_err_t rv = CONFIG_ERR_FATAL_ERROR; config_err_t ret; char *readable_str; char *threshold_str; uint8_t readable; uint8_t threshold_raw; uint64_t val; double threshold_calc; uint8_t sensor_number; assert (section_name); assert (kv); assert (arg); state_data = (ipmi_sensors_config_state_data_t *)arg; if ((ret = seek_to_sdr_record (state_data, section_name)) != CONFIG_ERR_SUCCESS) { rv = ret; goto cleanup; } if (ipmi_sdr_parse_sensor_number (state_data->sdr_ctx, NULL, 0, &sensor_number) < 0) { pstdout_fprintf (state_data->pstate, stderr, "ipmi_sdr_parse_sensor_number: %s\n", ipmi_sdr_ctx_errormsg (state_data->sdr_ctx)); goto cleanup; } if (!(obj_cmd_rs = fiid_obj_create (tmpl_cmd_get_sensor_thresholds_rs))) { pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_create: %s\n", strerror (errno)); goto cleanup; } if (ipmi_cmd_get_sensor_thresholds (state_data->ipmi_ctx, sensor_number, obj_cmd_rs) < 0) { if (state_data->prog_data->args->config_args.common_args.debug) pstdout_fprintf (state_data->pstate, stderr, "ipmi_cmd_get_sensor_thresholds: %s\n", ipmi_ctx_errormsg (state_data->ipmi_ctx)); if (config_is_non_fatal_error (state_data->ipmi_ctx, obj_cmd_rs, &ret)) rv = ret; /* * IPMI Workaround (achu) * * Discovered on HP DL585 * * Seems that the HP machine doesn't support the "Get Sensor * Thresholds" command. 99% of the time if a command is invalid * on a remote machine, that's a fatal error and we should exit. * I suppose this is an exception though. We can continue on * even if this command isn't supported. The user just doesn't * get to configure these thresholds. */ if (ipmi_ctx_errnum (state_data->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE && ipmi_check_completion_code (obj_cmd_rs, IPMI_COMP_CODE_INVALID_COMMAND) == 1) rv = CONFIG_ERR_NON_FATAL_ERROR; goto cleanup; } if (!strcasecmp (kv->key->key_name, "Lower_Non_Critical_Threshold")) { readable_str = "readable_thresholds.lower_non_critical_threshold"; threshold_str = "lower_non_critical_threshold"; } else if (!strcasecmp (kv->key->key_name, "Lower_Critical_Threshold")) { readable_str = "readable_thresholds.lower_critical_threshold"; threshold_str = "lower_critical_threshold"; } else if (!strcasecmp (kv->key->key_name, "Lower_Non_Recoverable_Threshold")) { readable_str = "readable_thresholds.lower_non_recoverable_threshold"; threshold_str = "lower_non_recoverable_threshold"; } else if (!strcasecmp (kv->key->key_name, "Upper_Non_Critical_Threshold")) { readable_str = "readable_thresholds.upper_non_critical_threshold"; threshold_str = "upper_non_critical_threshold"; } else if (!strcasecmp (kv->key->key_name, "Upper_Critical_Threshold")) { readable_str = "readable_thresholds.upper_critical_threshold"; threshold_str = "upper_critical_threshold"; } else if (!strcasecmp (kv->key->key_name, "Upper_Non_Recoverable_Threshold")) { readable_str = "readable_thresholds.upper_non_recoverable_threshold"; threshold_str = "upper_non_recoverable_threshold"; } else /* unknown key_name - fatal error */ goto cleanup; if (FIID_OBJ_GET (obj_cmd_rs, readable_str, &val) < 0) { pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_get: '%s': %s\n", readable_str, fiid_obj_errormsg (obj_cmd_rs)); goto cleanup; } readable = val; if (!readable) { /* Inconsistency w/ the SDR, should be readable */ if (state_data->prog_data->args->config_args.common_args.debug) pstdout_fprintf (state_data->pstate, stderr, "%s:%s - threshold not readable\n", section_name, kv->key->key_name); rv = CONFIG_ERR_NON_FATAL_ERROR; goto cleanup; } if (FIID_OBJ_GET (obj_cmd_rs, threshold_str, &val) < 0) { pstdout_fprintf (state_data->pstate, stderr, "fiid_obj_get: '%s': %s\n", threshold_str, fiid_obj_errormsg (obj_cmd_rs)); goto cleanup; } threshold_raw = val; if ((ret = _decode_value (state_data, threshold_raw, &threshold_calc)) != CONFIG_ERR_SUCCESS) { rv = ret; goto cleanup; } if (config_section_update_keyvalue_output_double (state_data->pstate, kv, threshold_calc) < 0) goto cleanup; rv = CONFIG_ERR_SUCCESS; cleanup: fiid_obj_destroy (obj_cmd_rs); return (rv); }