Example #1
0
char *config_get(const char *section, const char *name, const char *default_value)
{
	struct config_value *cv;

	debug(D_CONFIG, "request to get config in section '%s', name '%s', default_value '%s'", section, name, default_value);

	struct config *co = config_section_find(section);
	if(!co) co = config_section_create(section);

	cv = config_value_index_find(co, name, 0);
	if(!cv) {
		cv = config_value_create(co, name, default_value);
		if(!cv) return NULL;
	}
	cv->flags |= CONFIG_VALUE_USED;

	if((cv->flags & CONFIG_VALUE_LOADED) || (cv->flags & CONFIG_VALUE_CHANGED)) {
		// this is a loaded value from the config file
		// if it is different that the default, mark it
		if(!(cv->flags & CONFIG_VALUE_CHECKED)) {
			if(strcmp(cv->value, default_value) != 0) cv->flags |= CONFIG_VALUE_CHANGED;
			cv->flags |= CONFIG_VALUE_CHECKED;
		}
	}

	return(cv->value);
}
Example #2
0
EXPORT m64p_error CALL ConfigOpenSection(const char *SectionName, m64p_handle *ConfigSectionHandle)
{
    config_section **curr_section;
    config_section *new_section;

    if (!l_ConfigInit)
        return M64ERR_NOT_INIT;
    if (SectionName == NULL || ConfigSectionHandle == NULL)
        return M64ERR_INPUT_ASSERT;

    /* walk through the section list, looking for a case-insensitive name match */
    curr_section = find_alpha_section_link(&l_ConfigListActive, SectionName);
    if (*curr_section != NULL && osal_insensitive_strcmp(SectionName, (*curr_section)->name) == 0)
    {
        *ConfigSectionHandle = *curr_section;
        return M64ERR_SUCCESS;
    }

    /* didn't find the section, so create new one */
    new_section = config_section_create(SectionName);
    if (new_section == NULL)
        return M64ERR_NO_MEMORY;

    /* add section to list in alphabetical order */
    new_section->next = *curr_section;
    *curr_section = new_section;

    *ConfigSectionHandle = new_section;
    return M64ERR_SUCCESS;
}
struct config_section *
bmc_config_serial_channel_section_get (bmc_config_state_data_t *state_data)
{
  struct config_section * serial_channel_section = NULL;
  char *section_comment = 
    "In the Serial_Channel section, IPMI over Serial communication can be "
    "enabled or disabled.  "
    "In the below, \"Volatile\" configurations are immediately "
    "configured onto the BMC and will have immediate effect on the system.  "
    "\"Non_Volatile\" configurations are only available after the next "
    "system reset.  Generally, both the \"Volatile\" and \"Non_Volatile\" "
    "equivalent fields should be configured identically."
    "\n"
    "Most users will only be interested in IPMI over LAN, therefore serial "
    "communication can be disabled.  This can be done by setting "
    "\"Access_Mode\" to \"Disabled\".";
  unsigned int verbose_flags = 0;

  /*  
   * achu: section not checked out by default.
   */

  if (state_data->prog_data->args->config_args.verbose)
    verbose_flags = 0;
  else
    verbose_flags = CONFIG_DO_NOT_CHECKOUT;

  if (!(serial_channel_section = config_section_create (state_data->pstate,
                                                        "Serial_Channel",
                                                        "Serial_Channel",
                                                        section_comment,
                                                        verbose_flags,
                                                        NULL,
                                                        NULL)))
    goto cleanup;

  if (bmc_config_channel_common_section_get(state_data, 
                                            serial_channel_section,
                                            verbose_flags) < 0)
    goto cleanup;

  return serial_channel_section;

 cleanup:
  if (serial_channel_section)
    config_section_destroy(state_data->pstate, serial_channel_section);
  return NULL;
}
struct config_section *
bmc_config_lan_conf_security_keys_section_get (bmc_config_state_data_t *state_data)
{
  struct config_section *lan_conf_security_keys_section = NULL;
  char *section_comment = 
    "If your system supports IPMI 2.0 and Serial-over-LAN (SOL), a "
    "K_g BMC key may be configurable.  The K_g key is an optional key that "
    "can be set for two key authentication in IPMI 2.0.  It is optionally "
    "configured.  Most users will want to set this to zero (or blank).";

  if (!(lan_conf_security_keys_section = config_section_create (state_data->pstate,
                                                                "Lan_Conf_Security_Keys",
                                                                "Lan_Conf_Security_Keys",
                                                                section_comment,
                                                                0,
                                                                NULL,
                                                                NULL)))
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              lan_conf_security_keys_section,
                              "K_R",
                              "Give string or blank to clear. Max 20 chars",
                              0,
                              k_r_checkout,
                              k_r_commit,
                              k_r_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              lan_conf_security_keys_section,
                              "K_G",
                              "Give string or blank to clear. Max 20 bytes, prefix with 0x to enter hex",
                              0,
                              k_g_checkout,
                              k_g_commit,
                              k_g_validate) < 0)
    goto cleanup;

  return lan_conf_security_keys_section;

 cleanup:
  if (lan_conf_security_keys_section)
    config_section_destroy(state_data->pstate, lan_conf_security_keys_section);
  return NULL;
}
struct config_section *
bmc_config_lan_channel_section_get (bmc_config_state_data_t *state_data)
{
  struct config_section * lan_channel_section = NULL;
  char *section_comment = 
    "In the Lan_Channel section, general IPMI over LAN can be enabled for "
    "disabled.  In the below, \"Volatile\" configurations are immediately "
    "configured onto the BMC and will have immediate effect on the system.  "
    "\"Non_Volatile\" configurations are only available after the next "
    "system reset.  Generally, both the \"Volatile\" and \"Non_Volatile\" "
    "equivalent fields should be configured identically."
    "\n"
    "To enable IPMI over LAN, typically \"Access_Mode\" "
    "should be set to \"Always_Available\".  "
    "\"Channel_Privilege_Limit\" should be set to the highest privilege "
    "level any username was configured with.  Typically, this "
    "is set to \"Administrator\"."
    "\n"
    "\"User_Level_Auth\" and \"Per_Message_Auth\" are typically set to "
    "\"Yes\" for additional security.";

  if (!(lan_channel_section = config_section_create (state_data->pstate,
                                                     "Lan_Channel",
                                                     "Lan_Channel",
                                                     section_comment,
                                                     0,
                                                     NULL,
                                                     NULL)))
    goto cleanup;

  if (bmc_config_channel_common_section_get(state_data, 
                                            lan_channel_section,
                                            0) < 0)
    goto cleanup;

  return lan_channel_section;

 cleanup:
  if (lan_channel_section)
    config_section_destroy(state_data->pstate, lan_channel_section);
  return NULL;
}
Example #6
0
const char *config_set(const char *section, const char *name, const char *value)
{
	struct config_value *cv;

	debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value);

	struct config *co = config_section_find(section);
	if(!co) co = config_section_create(section);

	cv = config_value_index_find(co, name, 0);
	if(!cv) cv = config_value_create(co, name, value);
	cv->flags |= CONFIG_VALUE_USED;

	if(strcmp(cv->value, value) != 0) {
		cv->flags |= CONFIG_VALUE_CHANGED;

		free(cv->value);
		cv->value = strdup(value);
		if(!cv->value) fatal("Cannot allocate config.value");
	}

	return value;
}
struct config_section *
pef_config_alert_policy_table_section_get (pef_config_state_data_t *state_data, int num)
{
  struct config_section *section = NULL;
  uint8_t lan_channel_number;
  char *strp = NULL;
  config_err_t ret;
  char buf[CONFIG_MAX_SECTION_NAME_LEN];

  if (num <= 0)
    {
      pstdout_fprintf(state_data->pstate,
                      stderr, 
                      "Invalid Num = %d\n",
                      num);
      return NULL;
    }

  snprintf(buf, CONFIG_MAX_SECTION_NAME_LEN, "Alert_Policy_%d", num);

  if (!(section = config_section_create (state_data->pstate, 
                                         buf, 
                                         NULL, 
                                         NULL, 
                                         0,
                                         NULL,
                                         NULL)))
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              section,
                              "Policy_Type",
                              "Possible values: Always_Send_To_This_Destination/Proceed_To_Next_Entry/Do_Not_Proceed_Any_More_Entries/Proceed_To_Next_Entry_Different_Channel/Proceed_To_Next_Entry_Different_Destination_Type",
                              0,
                              policy_type_checkout,
                              policy_type_commit,
                              policy_type_validate) < 0) 
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              section,
                              "Policy_Enabled",
                              "Possible values: Yes/No",
                              0,
                              policy_enabled_checkout,
                              policy_enabled_commit,
                              config_yes_no_validate) < 0) 
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              section,
                              "Policy_Number",
                              "Give a valid number",
                              0,
                              policy_number_checkout,
                              policy_number_commit,
                              config_number_range_four_bits) < 0) 
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              section,
                              "Destination_Selector",
                              "Give a valid number",
                              0,
                              destination_selector_checkout,
                              destination_selector_commit,
                              config_number_range_four_bits) < 0) 
    goto cleanup;

  ret = get_lan_channel_number (state_data, &lan_channel_number);
  if (ret == CONFIG_ERR_SUCCESS)
    {
      if (asprintf(&strp, 
                   "Give a valid number (LAN = %u)", 
                   lan_channel_number) < 0)
        {
          if (!strp)
            {
              pstdout_perror(state_data->pstate,
                             "asprintf");
              goto cleanup;
            }
        }
    }
  else
    {
      if (!(strp = strdup("Give a valid number")))
        {
          pstdout_perror(state_data->pstate,
                         "strdup");
          goto cleanup;
        }
    }

  if (config_section_add_key (state_data->pstate, 
                              section,
                              "Channel_Number",
                              strp,
                              0,
                              channel_number_checkout,
                              channel_number_commit,
                              config_number_range_four_bits) < 0) 
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              section,
                              "Alert_String_Set_Selector",
                              "Give a valid number",
                              0,
                              alert_string_set_selector_checkout,
                              alert_string_set_selector_commit,
                              config_number_range_seven_bits) < 0) 
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              section,
                              "Event_Specific_Alert_String",
                              "Possible values: Yes/No",
                              0,
                              event_specific_alert_string_checkout,
                              event_specific_alert_string_commit,
                              config_yes_no_validate) < 0) 
    goto cleanup;

  if (strp)
    free(strp);
  return section;

 cleanup:
  if (strp)
    free(strp);
  if (section)
    config_section_destroy(state_data->pstate, section);
  return NULL;
}
Example #8
0
static config_section * section_deepcopy(config_section *orig_section)
{
    config_section *new_section;
    config_var *orig_var, *last_new_var;

    /* Input validation */
    if (orig_section == NULL)
        return NULL;

    /* create and copy section struct */
    new_section = config_section_create(orig_section->name);
    if (new_section == NULL)
        return NULL;

    /* create and copy all section variables */
    orig_var = orig_section->first_var;
    last_new_var = NULL;
    while (orig_var != NULL)
    {
        config_var *new_var = config_var_create(orig_var->name, orig_var->comment);
        if (new_var == NULL)
        {
            delete_section(new_section);
            return NULL;
        }

        new_var->type = orig_var->type;
        switch (orig_var->type)
        {
            case M64TYPE_INT:
            case M64TYPE_BOOL:
                new_var->val.integer = orig_var->val.integer;
                break;
                
            case M64TYPE_FLOAT:
                new_var->val.number = orig_var->val.number;
                break;

            case M64TYPE_STRING:
                if (orig_var->val.string != NULL)
                {
                    new_var->val.string = strdup(orig_var->val.string);
                    if (new_var->val.string == NULL)
                    {
                        delete_section(new_section);
                        return NULL;
                    }
                }
                else
                    new_var->val.string = NULL;

                break;
        }

        /* add the new variable to the new section */
        if (last_new_var == NULL)
            new_section->first_var = new_var;
        else
            last_new_var->next = new_var;
        last_new_var = new_var;
        /* advance variable pointer in original section variable list */
        orig_var = orig_var->next;
    }

    return new_section;
}
struct config_section *
ipmi_pef_config_alert_policy_table_section_get (ipmi_pef_config_state_data_t *state_data, unsigned int num)
{
  struct config_section *section = NULL;
  char section_name[CONFIG_MAX_SECTION_NAME_LEN];
  char description[CONFIG_MAX_DESCRIPTION_LEN];

  assert (state_data);
  assert (num);

  snprintf (section_name, CONFIG_MAX_SECTION_NAME_LEN, "Alert_Policy_%u", num);

  if (!(section = config_section_create (state_data->pstate,
                                         section_name,
                                         NULL,
                                         NULL,
                                         0,
                                         NULL,
                                         NULL)))
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              section,
                              "Policy_Type",
                              "Possible values: Always_Send_To_This_Destination/Proceed_To_Next_Entry/Do_Not_Proceed_Any_More_Entries/Proceed_To_Next_Entry_Different_Channel/Proceed_To_Next_Entry_Different_Destination_Type",
                              0,
                              policy_type_checkout,
                              policy_type_commit,
                              policy_type_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              section,
                              "Policy_Enabled",
                              "Possible values: Yes/No",
                              0,
                              policy_enabled_checkout,
                              policy_enabled_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              section,
                              "Policy_Number",
                              "Give a valid number",
                              0,
                              policy_number_checkout,
                              policy_number_commit,
                              config_number_range_four_bits) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              section,
                              "Destination_Selector",
                              "Give a valid number",
                              0,
                              destination_selector_checkout,
                              destination_selector_commit,
                              config_number_range_four_bits) < 0)
    goto cleanup;

  if (!state_data->lan_channel_numbers_loaded)
    {
      if (load_lan_channel_numbers (state_data) != CONFIG_ERR_SUCCESS)
	goto cleanup;
    }

  if (state_data->lan_channel_numbers_count > 0)
    {
      char tempbuf[CONFIG_MAX_DESCRIPTION_LEN];
      int i;

      snprintf (description,
		CONFIG_MAX_DESCRIPTION_LEN,
		"Give a valid number (LAN = %u",
		state_data->lan_channel_numbers[0]);

      for (i = 1; i < state_data->lan_channel_numbers_count; i++)
	{
	  snprintf (tempbuf,
		    CONFIG_MAX_DESCRIPTION_LEN,
		    ", %u",
		    state_data->lan_channel_numbers[i]);
	  
	  strcat (description, tempbuf);
	}

      strcat (description, ")");
    }
  else
    snprintf (description,
	      CONFIG_MAX_DESCRIPTION_LEN,
	      "Give a valid number");

  if (config_section_add_key (state_data->pstate,
                              section,
                              "Channel_Number",
                              description,
                              0,
                              channel_number_checkout,
                              channel_number_commit,
                              config_number_range_four_bits) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              section,
                              "Alert_String_Set_Selector",
                              "Give a valid number",
                              0,
                              alert_string_set_selector_checkout,
                              alert_string_set_selector_commit,
                              config_number_range_seven_bits) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              section,
                              "Event_Specific_Alert_String",
                              "Possible values: Yes/No",
                              0,
                              event_specific_alert_string_checkout,
                              event_specific_alert_string_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  return (section);

 cleanup:
  if (section)
    config_section_destroy (section);
  return (NULL);
}
Example #10
0
int load_config(char *filename, int overwrite_used)
{
	int line = 0;
	struct config *co = NULL;

	char buffer[CONFIG_FILE_LINE_MAX + 1], *s;

	if(!filename) filename = CONFIG_DIR "/" CONFIG_FILENAME;
	FILE *fp = fopen(filename, "r");
	if(!fp) {
		error("Cannot open file '%s'", filename);
		return 0;
	}

	while(fgets(buffer, CONFIG_FILE_LINE_MAX, fp) != NULL) {
		buffer[CONFIG_FILE_LINE_MAX] = '\0';
		line++;

		s = trim(buffer);
		if(!s) {
			debug(D_CONFIG, "Ignoring line %d, it is empty.", line);
			continue;
		}

		int len = (int) strlen(s);
		if(*s == '[' && s[len - 1] == ']') {
			// new section
			s[len - 1] = '\0';
			s++;

			co = config_section_find(s);
			if(!co) co = config_section_create(s);

			continue;
		}

		if(!co) {
			// line outside a section
			error("Ignoring line %d ('%s'), it is outside all sections.", line, s);
			continue;
		}

		char *name = s;
		char *value = strchr(s, '=');
		if(!value) {
			error("Ignoring line %d ('%s'), there is no = in it.", line, s);
			continue;
		}
		*value = '\0';
		value++;

		name = trim(name);
		value = trim(value);

		if(!name) {
			error("Ignoring line %d, name is empty.", line);
			continue;
		}
		if(!value) {
			debug(D_CONFIG, "Ignoring line %d, value is empty.", line);
			continue;
		}

		struct config_value *cv = config_value_index_find(co, name, 0);

		if(!cv) cv = config_value_create(co, name, value);
		else {
			if(((cv->flags & CONFIG_VALUE_USED) && overwrite_used) || !(cv->flags & CONFIG_VALUE_USED)) {
				debug(D_CONFIG, "Line %d, overwriting '%s/%s'.", line, co->name, cv->name);
				free(cv->value);
				cv->value = strdup(value);
				if(!cv->value) fatal("Cannot allocate config.value");
			}
			else
				debug(D_CONFIG, "Ignoring line %d, '%s/%s' is already present and used.", line, co->name, cv->name);
		}
		cv->flags |= CONFIG_VALUE_LOADED;
	}

	fclose(fp);

	return 1;
}
struct config_section *
pef_config_pef_conf_section_get (pef_config_state_data_t *state_data)
{
  struct config_section *pef_section;

  if (!(pef_section = config_section_create (state_data->pstate, 
                                             "PEF_Conf",
                                             NULL,
                                             NULL,
                                             0,
                                             NULL,
                                             NULL)))
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Enable_PEF",
                              "Possible values: Yes/No",
                              0,
                              _enable_pef_checkout,
                              _enable_pef_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Enable_PEF_Event_Messages",
                              "Possible values: Yes/No",
                              0,
                              _enable_pef_event_messages_checkout,
                              _enable_pef_event_messages_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Enable_PEF_Startup_Delay",
                              "Possible values: Yes/No",
                              0,
                              _enable_pef_startup_delay_checkout,
                              _enable_pef_startup_delay_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Enable_PEF_Alert_Startup_Delay",
                              "Possible values: Yes/No",
                              0,
                              _enable_pef_alert_startup_delay_checkout,
                              _enable_pef_alert_startup_delay_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;
  
  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Enable_Alert_Action",
                              "Possible values: Yes/No",
                              0,
                              _enable_alert_action_checkout,
                              _enable_alert_action_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Enable_Power_Down_Action",
                              "Possible values: Yes/No",
                              0,
                              _enable_power_down_action_checkout,
                              _enable_power_down_action_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Enable_Reset_Action",
                              "Possible values: Yes/No",
                              0,
                              _enable_reset_action_checkout,
                              _enable_reset_action_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Enable_Power_Cycle_Action",
                              "Possible values: Yes/No",
                              0,
                              _enable_power_cycle_action_checkout,
                              _enable_power_cycle_action_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Enable_OEM_Action",
                              "Possible values: Yes/No",
                              0,
                              _enable_oem_action_checkout,
                              _enable_oem_action_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Enable_Diagnostic_Interrupt",
                              "Possible values: Yes/No",
                              0,
                              _enable_diagnostic_interrupt_checkout,
                              _enable_diagnostic_interrupt_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Startup_Delay",
                              "Give value in seconds",
                              0,
                              _pef_startup_delay_checkout,
                              _pef_startup_delay_commit,
                              config_number_range_one_byte) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate, 
                              pef_section,
                              "Alert_Startup_Delay",
                              "Give value in seconds",
                              0,
                              _pef_alert_startup_delay_checkout,
                              _pef_alert_startup_delay_commit,
                              config_number_range_one_byte) < 0)
    goto cleanup;

  return pef_section;

 cleanup:
  if (pef_section)
    config_section_destroy(state_data->pstate, pef_section);
  return NULL;
}
struct config_section *
bmc_config_sol_conf_section_get (bmc_config_state_data_t *state_data)
{
  struct config_section * sol_conf_section = NULL;
  char *section_comment = 
    "If your system supports IPMI 2.0 and Serial-over-LAN (SOL), the "
    "following configuration options will allow SOL configuration."
    "\n"
    "For most users that want to enable SOL, minimally \"Enable_SOL\" "
    "should be set to \"Yes\" and \"SOL_Privilege_Level\" should be set to "
    "the highest privilege level any username configured can authenticate "
    "with (typically \"Administrator\").  For security purposes, "
    "\"Force_SOL_Payload_Authentication\" and "
    "\"Force_SOL_Payload_Encryption\" should be set to \"Yes\", however "
    "forced authentication and/or encryption depends on the cipher suite "
    "IDs supported. The \"Non_Volatile_Bit_Rate\" "
    "and \"Volatile_Bit_Rate\" should both be set to the appropriate baud "
    "rate for your system.  This is typically the same baud rate configured "
    "in the BIOS and/or operating system.";

  if (!(sol_conf_section = config_section_create(state_data->pstate,
                                                 "SOL_Conf",
                                                 "SOL_Conf",
                                                 section_comment,
                                                 0,
                                                 NULL,
                                                 NULL)))
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              sol_conf_section,
                              "Enable_SOL",
                              "Possible values: Yes/No",
                              0,
                              enable_sol_checkout,
                              enable_sol_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              sol_conf_section,
                              "SOL_Privilege_Level",
                              "Possible values: Callback/User/Operator/Administrator/OEM_Proprietary",
                              0,
                              sol_privilege_level_checkout,
                              sol_privilege_level_commit,
                              privilege_level_number_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              sol_conf_section,
                              "Force_SOL_Payload_Authentication",
                              "Possible values: Yes/No",
                              0,
                              force_sol_payload_authentication_checkout,
                              force_sol_payload_authentication_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              sol_conf_section,
                              "Force_SOL_Payload_Encryption",
                              "Possible values: Yes/No",
                              0,
                              force_sol_payload_encryption_checkout,
                              force_sol_payload_encryption_commit,
                              config_yes_no_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              sol_conf_section,
                              "Character_Accumulate_Interval",
                              "Give a non-zero valid integer. Each unit is 5ms",
                              0,
                              character_accumulate_interval_checkout,
                              character_accumulate_interval_commit,
                              config_number_range_one_byte_non_zero) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              sol_conf_section,
                              "Character_Send_Threshold",
                              "Give a valid number",
                              0,
                              character_send_threshold_checkout,
                              character_send_threshold_commit,
                              config_number_range_one_byte) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              sol_conf_section,
                              "SOL_Retry_Count",
                              "Give a valid integer",
                              0,
                              sol_retry_count_checkout,
                              sol_retry_count_commit,
                              config_number_range_one_byte) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              sol_conf_section,
                              "SOL_Retry_Interval",
                              "Give a valid integer. Interval unit is 10ms",
                              0,
                              sol_retry_interval_checkout,
                              sol_retry_interval_commit,
                              config_number_range_one_byte) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              sol_conf_section,
                              "Non_Volatile_Bit_Rate",
                              "Possible values: Serial/9600/19200/38400/57600/115200",
                              0,
                              non_volatile_bit_rate_checkout,
                              non_volatile_bit_rate_commit,
                              sol_bit_rate_number_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              sol_conf_section,
                              "Volatile_Bit_Rate",
                              "Possible values: Serial/9600/19200/38400/57600/115200",
                              0,
                              volatile_bit_rate_checkout,
                              volatile_bit_rate_commit,
                              sol_bit_rate_number_validate) < 0)
    goto cleanup;

  if (config_section_add_key (state_data->pstate,
                              sol_conf_section,
                              "SOL_Payload_Port_Number",
                              "Give a valid port number",
                              CONFIG_CHECKOUT_KEY_COMMENTED_OUT,
                              sol_payload_port_checkout,
                              sol_payload_port_commit,
                              config_number_range_two_bytes) < 0)
    goto cleanup;

  return sol_conf_section;

 cleanup:
  if (sol_conf_section)
    config_section_destroy(state_data->pstate, sol_conf_section);
  return NULL;
}
config_err_t
ipmi_sensors_config_threshold_section (ipmi_sensors_config_state_data_t *state_data,
                                       struct config_section **section_ptr)
{
  struct config_section *section = NULL;
  char section_name[CONFIG_MAX_SECTION_NAME_LEN];
  uint8_t threshold_access_support = 0;
  uint8_t hysteresis_support = 0;
  config_err_t rv = CONFIG_ERR_FATAL_ERROR;
  config_err_t ret;
  uint8_t sensor_type;
  uint8_t sensor_units_percentage;
  uint8_t sensor_units_modifier;
  uint8_t sensor_units_rate;
  uint8_t sensor_base_unit_type;
  uint8_t sensor_modifier_unit_type;
  char description[CONFIG_MAX_DESCRIPTION_LEN];
  char sensor_units_buf[IPMI_SENSORS_CONFIG_UNITS_BUFLEN+1];
  int sensor_units_ret;
  const char *sensor_type_str = NULL;

  assert (state_data);
  assert (section_ptr);

  if ((ret = create_section_name (state_data,
                                  section_name,
                                  CONFIG_MAX_SECTION_NAME_LEN)) != CONFIG_ERR_SUCCESS)
    {
      if (state_data->prog_data->args->config_args.common_args.debug)
        pstdout_fprintf (state_data->pstate,
                         stderr,
                         "create_section_name: %s\n",
                         strerror (errno));
      rv = ret;
      goto cleanup;
    }

  if (!(section = config_section_create (state_data->pstate,
                                         section_name,
                                         NULL,
                                         NULL,
                                         0,
                                         NULL,
                                         NULL)))
    goto cleanup;

  if (ipmi_sdr_parse_sensor_capabilities (state_data->sdr_ctx,
					  NULL,
					  0,
                                          NULL,
                                          &threshold_access_support,
                                          &hysteresis_support,
                                          NULL,
                                          NULL) < 0)
    {
      pstdout_fprintf (state_data->pstate,
                       stderr,
                       "ipmi_sdr_parse_sensor_capabilities: %s\n",
                       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      goto cleanup;
    }

  if (ipmi_sdr_parse_sensor_type (state_data->sdr_ctx,
				  NULL,
				  0,
                                  &sensor_type) < 0)
    {
      pstdout_fprintf (state_data->pstate,
                       stderr,
                       "ipmi_sdr_parse_sensor_type: %s\n",
                       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      goto cleanup;
    }

  if (ipmi_sdr_parse_sensor_units (state_data->sdr_ctx,
				   NULL,
				   0,
                                   &sensor_units_percentage,
                                   &sensor_units_modifier,
                                   &sensor_units_rate,
                                   &sensor_base_unit_type,
                                   &sensor_modifier_unit_type) < 0)
    {
      pstdout_fprintf (state_data->pstate,
                       stderr,
                       "ipmi_sdr_parse_sensor_unit: %s\n",
                       ipmi_sdr_ctx_errormsg (state_data->sdr_ctx));
      goto cleanup;
    }

  memset (sensor_units_buf, '\0', IPMI_SENSORS_CONFIG_UNITS_BUFLEN);
  sensor_units_ret = ipmi_sensor_units_string (sensor_units_percentage,
                                               sensor_units_modifier,
                                               sensor_units_rate,
                                               sensor_base_unit_type,
                                               sensor_modifier_unit_type,
                                               sensor_units_buf,
                                               IPMI_SENSORS_CONFIG_UNITS_BUFLEN,
                                               0);

  sensor_type_str = ipmi_get_sensor_type_string (sensor_type);

  memset (description, '\0', CONFIG_MAX_DESCRIPTION_LEN);
  if (sensor_units_ret > 0)
    snprintf (description,
              CONFIG_MAX_DESCRIPTION_LEN,
              "Give valid input for sensor type = %s; units = %s",
              sensor_type_str ? sensor_type_str : UNRECOGNIZED_SENSOR_TYPE,
              sensor_units_buf);
  else
    snprintf (description,
              CONFIG_MAX_DESCRIPTION_LEN,
              "Give valid input for sensor type = %s",
              sensor_type_str ? sensor_type_str : UNRECOGNIZED_SENSOR_TYPE);
  
  if (setup_sensor_event_enable_fields (state_data, section) < 0)
    goto cleanup;

  if (threshold_access_support == IPMI_SDR_READABLE_THRESHOLDS_SUPPORT
      || threshold_access_support == IPMI_SDR_READABLE_SETTABLE_THRESHOLDS_SUPPORT
      || state_data->prog_data->args->config_args.verbose_count)
    {
      if (_setup_threshold_fields (state_data,
                                   section,
                                   description,
                                   sensor_base_unit_type) < 0)
        goto cleanup;
    }

  if (hysteresis_support == IPMI_SDR_READABLE_HYSTERESIS_SUPPORT
      || hysteresis_support == IPMI_SDR_READABLE_SETTABLE_HYSTERESIS_SUPPORT
      || state_data->prog_data->args->config_args.verbose_count)
    {
      if (_setup_threshold_hysteresis_fields (state_data,
                                              section,
                                              description,
                                              sensor_base_unit_type,
                                              hysteresis_support) < 0)
        goto cleanup;
    }

  *section_ptr = section;
  return (CONFIG_ERR_SUCCESS);

 cleanup:
  if (section)
    config_section_destroy (section);
  return (rv);
}