/* * Copyright (C) 2008-2015 FreeIPMI Core Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #if HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #if STDC_HEADERS #include #endif /* STDC_HEADERS */ #include #include #include #include "ipmi-oem.h" #include "ipmi-oem-argp.h" #include "ipmi-oem-common.h" #include "freeipmi-portability.h" #include "pstdout.h" int ipmi_oem_check_response_and_completion_code (ipmi_oem_state_data_t *state_data, const void *bytes_rs, unsigned int bytes_rs_len, unsigned int expected_bytes_rs_len, uint8_t cmd, uint8_t netfn, Ipmi_oem_comp_code_strerror comp_code_strerror) { const uint8_t *bytes_rs_ptr = bytes_rs; assert (state_data); assert (bytes_rs); if (bytes_rs_len < expected_bytes_rs_len) { if (bytes_rs_len >= 2 && bytes_rs_ptr[1] != IPMI_COMP_CODE_COMMAND_SUCCESS) goto output_comp_code_error; pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid response length: %u, expected %u\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, bytes_rs_len, expected_bytes_rs_len); return (-1); } output_comp_code_error: if (bytes_rs_ptr[1] != IPMI_COMP_CODE_COMMAND_SUCCESS) { char errbuf[IPMI_OEM_ERR_BUFLEN + 1]; memset (errbuf, '\0', IPMI_OEM_ERR_BUFLEN + 1); if (comp_code_strerror) { int ret; if ((ret = comp_code_strerror (state_data, bytes_rs_ptr[1], /* completion code */ cmd, netfn, errbuf, IPMI_OEM_ERR_BUFLEN)) < 0) snprintf (errbuf, IPMI_OEM_ERR_BUFLEN, "completion-code = 0x%X", bytes_rs_ptr[1]); if (!ret) goto standard_output_comp_code_error; } else { standard_output_comp_code_error: if (ipmi_completion_code_strerror_r (cmd, /* cmd */ netfn, /* network function */ bytes_rs_ptr[1], /* completion code */ errbuf, IPMI_OEM_ERR_BUFLEN) < 0) { #if 0 pstdout_perror (state_data->pstate, "ipmi_completion_code_strerror_r"); #endif snprintf (errbuf, IPMI_OEM_ERR_BUFLEN, "completion-code = 0x%X", bytes_rs_ptr[1]); } } pstdout_fprintf (state_data->pstate, stderr, "%s:%s failed: %s\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, errbuf); return (-1); } return (0); } int ipmi_oem_parse_key_value (ipmi_oem_state_data_t *state_data, unsigned int option_num, char **key, char **value) { char *tempstr = NULL; char *tempptr = NULL; char *tempkey = NULL; char *tempvalue = NULL; int rv = -1; assert (state_data); assert (key); assert (value); if (!(tempstr = strdup (state_data->prog_data->args->oem_options[option_num]))) { pstdout_perror (state_data->pstate, "strdup"); goto cleanup; } tempptr = strchr (tempstr, '='); if (!tempptr) { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid OEM option argument '%s' : no equal sign\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[option_num]); goto cleanup; } (*tempptr) = '\0'; tempptr++; if (!(tempkey = strdup (tempstr))) { pstdout_perror (state_data->pstate, "strdup"); goto cleanup; } if (!(tempvalue = strdup (tempptr))) { pstdout_perror (state_data->pstate, "strdup"); goto cleanup; } (*key) = tempkey; (*value) = tempvalue; rv = 0; cleanup: free (tempstr); if (rv < 0) { free (tempkey); free (tempvalue); } return (rv); } int ipmi_oem_parse_enable (ipmi_oem_state_data_t *state_data, unsigned int option_num, const char *value, uint8_t *enable) { assert (state_data); assert (value); assert (enable); if (strcasecmp (value, "enable") && strcasecmp (value, "disable")) { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid OEM option argument '%s' : invalid value\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[option_num]); return (-1); } if (!strcasecmp (value, "enable")) (*enable) = 1; else (*enable) = 0; return (0); } int ipmi_oem_parse_1_byte_field (ipmi_oem_state_data_t *state_data, unsigned int option_num, const char *value, uint8_t *value_out) { unsigned int temp; char *ptr = NULL; assert (state_data); assert (value); assert (value_out); errno = 0; temp = strtoul (value, &ptr, 10); if (errno || ptr[0] != '\0' || temp > UCHAR_MAX) { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid OEM option argument '%s' : invalid value\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[option_num]); return (-1); } (*value_out) = temp; return (0); } int ipmi_oem_parse_2_byte_field (ipmi_oem_state_data_t *state_data, unsigned int option_num, const char *value, uint16_t *value_out) { unsigned int temp; char *ptr = NULL; assert (state_data); assert (value); assert (value_out); errno = 0; temp = strtoul (value, &ptr, 10); if (errno || ptr[0] != '\0' || temp > USHRT_MAX) { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid OEM option argument '%s' : invalid value\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[option_num]); return (-1); } (*value_out) = temp; return (0); } int ipmi_oem_parse_4_byte_field (ipmi_oem_state_data_t *state_data, unsigned int option_num, const char *value, uint32_t *value_out) { unsigned int temp; char *ptr = NULL; assert (state_data); assert (value); assert (value_out); errno = 0; temp = strtoul (value, &ptr, 10); if (errno || ptr[0] != '\0') { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid OEM option argument '%s' : invalid value\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[option_num]); return (-1); } (*value_out) = temp; return (0); } int ipmi_oem_parse_unsigned_int_range (ipmi_oem_state_data_t *state_data, unsigned int option_num, const char *value, uint32_t *value_out, unsigned int min, unsigned int max) { unsigned int temp; char *ptr = NULL; assert (state_data); assert (value); assert (value_out); assert (min < max); errno = 0; temp = strtoul (value, &ptr, 10); if (errno || ptr[0] != '\0') { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid OEM option argument '%s' : invalid value\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[option_num]); return (-1); } if (temp < min || temp > max) { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid OEM option argument '%s' : out of range\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[option_num]); return (-1); } (*value_out) = temp; return (0); } int ipmi_oem_parse_ip_address (ipmi_oem_state_data_t *state_data, unsigned int option_num, const char *value, uint32_t *ip_address) { unsigned int b1, b2, b3, b4; uint32_t temp; int ret; assert (state_data); assert (value); assert (ip_address); if ((ret = sscanf (value, "%u.%u.%u.%u", &b1, &b2, &b3, &b4)) < 0) { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid IP address '%s'\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[option_num]); return (-1); } if (ret != 4) { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid IP address '%s'\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[option_num]); return (-1); } temp = 0; temp |= (uint32_t)b1; temp |= ((uint32_t)b2 << 8); temp |= ((uint32_t)b3 << 16); temp |= ((uint32_t)b4 << 24); (*ip_address) = temp; return (0); } int ipmi_oem_parse_string (ipmi_oem_state_data_t *state_data, unsigned int option_num, const char *value, uint8_t *string_length, char *stringbuf, unsigned int stringbuflen) { assert (state_data); assert (value); assert (string_length); assert (stringbuf); assert (stringbuflen); if (strlen (value) > stringbuflen) { pstdout_fprintf (state_data->pstate, stderr, "%s:%s invalid OEM option argument '%s' : string length too long\n", state_data->prog_data->args->oem_id, state_data->prog_data->args->oem_command, state_data->prog_data->args->oem_options[option_num]); return (-1); } (*string_length) = strlen (value); /* use memcpy, do not need NULL termination */ if ((*string_length)) memcpy (stringbuf, value, (*string_length)); return (0); } 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); }