Example #1
0
static void typecheck_config_array(config_setting_t *array) {
	assert(config_setting_is_array(array));
	int length = config_setting_length(array);
	if (length > 6) die("Arrays must be fewer than seven elements.");
	for (int i = 0; i < length; i++) {
		config_setting_t *elem = config_setting_get_elem(array, i);
		int val = config_setting_get_int(elem);
		if (config_setting_type(elem) != CONFIG_TYPE_INT || val > 0xFF || val < -1) {
			die("Arrays must only contain numbers in the range -1 to 0xFF.");
		}
	}
}
Example #2
0
int read_volumes_local_config(config_t * config, bool reread)
{
	config_setting_t * settings = config_lookup(config, "volumes");
	if ((settings == NULL) && (config_setting_is_array(settings) != CONFIG_TRUE))
	{
		// failed to locate volumes configuration section
		message(LOG_ERROR, FACILITY_CONFIG, "Volumes local config section is missing, please add it to local config.\n");
		return CONFIG_FALSE;
	}

	config_setting_t * volume_setting;
	int i;
	// for each volume element
	for (i = 0; (volume_setting = config_setting_get_elem(settings, i)) != NULL; ++i)
	{
		uint64_t id = 0;
		uint64_t cache_size;
		const char * local_path;
		int rv;

		rv = config_setting_lookup_uint64_t(volume_setting, "id", &id);
		if (rv != CONFIG_TRUE || !is_valid_volume_id(id))
		{
			// failed to read volume_setting id from zfsd.config
			message(LOG_ERROR, FACILITY_CONFIG, "Volume id config key is wrong type or is missing in local config.\n");
			return CONFIG_FALSE;
		}

		rv = config_setting_lookup_uint64_t(volume_setting, "cache_size", &cache_size);
		if (rv != CONFIG_TRUE)
		{
			// failed to read volume_setting cache limit, assume 0 will be fine
			message(LOG_WARNING, FACILITY_CONFIG, "Volume cache_size key is wrong type or is missing in local config, assuming cache_size = 0.\n");
			cache_size = 0;
		}

		rv = config_setting_lookup_string(volume_setting, "local_path", &local_path);
		if (rv != CONFIG_TRUE)
		{
			// failed to get local path
			message(LOG_ERROR, FACILITY_CONFIG, "Volume local_path config keyi is wrong type or is missing in local config.\n");
			return CONFIG_FALSE;
		}

		create_volume_from_local_config(id, cache_size, local_path, reread);
	}

	return CONFIG_TRUE;
}
Example #3
0
static void typecheck_config_ifgroup(config_setting_t *ifgroup) {
	assert(config_setting_is_group(ifgroup));
	config_setting_t *dflt = config_setting_get_member(ifgroup, "default");
	config_setting_t *mac = config_setting_get_member(ifgroup, "mac");
	config_setting_t *interface = config_setting_get_member(ifgroup, "interface");

	if (dflt == NULL && interface == NULL)
		die("Interface group must contain either \"default\" or \"interface\" elements.");
	if (dflt != NULL && interface != NULL)
		die("Interface group must contain only one of \"default\" and \"interface\" elements.");
	if (mac == NULL)
		die("Interface group must contain a \"mac\" element.");
	if (dflt != NULL && config_setting_type(dflt) != CONFIG_TYPE_BOOL)
		die("Interface group element \"default\" must be a bool.");
	if (interface != NULL && config_setting_type(interface) != CONFIG_TYPE_STRING)
		die("Interface group element \"interface\" must be a string.");
	if (!config_setting_is_array(mac))
		die("Interface group element \"mac\" must be an array.");
	typecheck_config_array(mac);
}
Example #4
0
/*********************
return RET_NOK on error
*********************/
ret_code_t entry_copy_config(config_setting_t * source, config_setting_t * dest)
{
	config_setting_t * new_source;
	config_setting_t * new_dest;
	int index = -1;
	int int_value;
	long long long_value;
	double double_value;
	const char * string;

	while((new_source=config_setting_get_elem(source,index+1))!= NULL ) {
		index++;
		if(config_setting_is_group(new_source)) {
			if(!entry_copy_aggregate(new_source,dest,CONFIG_TYPE_GROUP)) {
				return RET_NOK;
			}
		}

		else if(config_setting_is_array(new_source)) {
			if(!entry_copy_aggregate(new_source,dest,CONFIG_TYPE_ARRAY)) {
				return RET_NOK;
			}
		}

		else if(config_setting_is_list(new_source)) {
			if(!entry_copy_aggregate(new_source,dest,CONFIG_TYPE_LIST)) {
				return RET_NOK;
			}
		}

		else {
			switch(config_setting_type(new_source)) {
			case CONFIG_TYPE_INT:
				int_value = config_setting_get_int(new_source);
				new_dest = config_setting_add (dest, config_setting_name(new_source),CONFIG_TYPE_INT);
				config_setting_set_int(new_dest,int_value);
				continue;
			case CONFIG_TYPE_INT64:
				long_value = config_setting_get_int64(new_source);
				new_dest = config_setting_add (dest, config_setting_name(new_source),CONFIG_TYPE_INT64);
				config_setting_set_int64(new_dest,long_value);
				continue;
			case CONFIG_TYPE_FLOAT:
				double_value = config_setting_get_float(new_source);
				new_dest = config_setting_add (dest, config_setting_name(new_source),CONFIG_TYPE_FLOAT);
				config_setting_set_float(new_dest,double_value);
				continue;
			case CONFIG_TYPE_BOOL:
				int_value = config_setting_get_bool(new_source);
				new_dest = config_setting_add (dest, config_setting_name(new_source),CONFIG_TYPE_BOOL);
				config_setting_set_bool(new_dest,int_value);
				continue;
			case CONFIG_TYPE_STRING:
				string = config_setting_get_string(new_source);
				new_dest = config_setting_add (dest, config_setting_name(new_source),CONFIG_TYPE_STRING);
				config_setting_set_string(new_dest,string);
				continue;
			default:
				return RET_NOK;
			}
		}
	}

	return RET_OK;
}
Example #5
0
static const char *test_libconfig_setting_types(void)
{
	struct config_t config;
	struct config_setting_t *t;
	const char *input = "/* Test File */\n"
		"Setting_Int: 1;\n"
		"Setting_Int64: 1L;\n"
		"Setting_Float: 1.0;\n"
		"Setting_Bool: true;\n"
		"Setting_String: \"1\";\n"
		"Setting_Array: [ ];\n"
		"Setting_Group: { };\n"
		"Setting_List: ( );\n"
		"/* End test file */\n";

	if (libconfig->read_string(&config, input) == CONFIG_FALSE) {
		libconfig->destroy(&config);
		return "Unable to parse configuration.";
	}

	if (config_setting_type(config.root) != CONFIG_TYPE_GROUP) {
		libconfig->destroy(&config);
		return "CONFIG_TYPE_GROUP failed.";
	}

	if ((t = libconfig->lookup(&config, "Setting_Int")) == NULL || config_setting_type(t) != CONFIG_TYPE_INT
			|| config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t)
			|| config_setting_is_aggregate(t) || !config_setting_is_scalar(t) || !config_setting_is_number(t)
	) {
		libconfig->destroy(&config);
		return "CONFIG_TYPE_INT failed.";
	}

	if ((t = libconfig->lookup(&config, "Setting_Int64")) == NULL || config_setting_type(t) != CONFIG_TYPE_INT64
			|| config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t)
			|| config_setting_is_aggregate(t) || !config_setting_is_scalar(t) || !config_setting_is_number(t)
	) {
		libconfig->destroy(&config);
		return "CONFIG_TYPE_INT64 failed.";
	}

	if ((t = libconfig->lookup(&config, "Setting_Float")) == NULL || config_setting_type(t) != CONFIG_TYPE_FLOAT
			|| config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t)
			|| config_setting_is_aggregate(t) || !config_setting_is_scalar(t) || !config_setting_is_number(t)
	) {
		libconfig->destroy(&config);
		return "CONFIG_TYPE_FLOAT failed.";
	}

	if ((t = libconfig->lookup(&config, "Setting_Bool")) == NULL || config_setting_type(t) != CONFIG_TYPE_BOOL
			|| config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t)
			|| config_setting_is_aggregate(t) || !config_setting_is_scalar(t) || config_setting_is_number(t)
	) {
		libconfig->destroy(&config);
		return "CONFIG_TYPE_BOOL failed.";
	}

	if ((t = libconfig->lookup(&config, "Setting_String")) == NULL || config_setting_type(t) != CONFIG_TYPE_STRING
			|| config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t)
			|| config_setting_is_aggregate(t) || !config_setting_is_scalar(t) || config_setting_is_number(t)
	) {
		libconfig->destroy(&config);
		return "CONFIG_TYPE_STRING failed.";
	}

	if ((t = libconfig->lookup(&config, "Setting_Array")) == NULL || config_setting_type(t) != CONFIG_TYPE_ARRAY
			|| config_setting_is_group(t) || !config_setting_is_array(t) || config_setting_is_list(t)
			|| !config_setting_is_aggregate(t) || config_setting_is_scalar(t) || config_setting_is_number(t)
	) {
		libconfig->destroy(&config);
		return "CONFIG_TYPE_ARRAY failed.";
	}

	if ((t = libconfig->lookup(&config, "Setting_Group")) == NULL || config_setting_type(t) != CONFIG_TYPE_GROUP
			|| !config_setting_is_group(t) || config_setting_is_array(t) || config_setting_is_list(t)
			|| !config_setting_is_aggregate(t) || config_setting_is_scalar(t) || config_setting_is_number(t)
	) {
		libconfig->destroy(&config);
		return "CONFIG_TYPE_GROUP failed.";
	}

	if ((t = libconfig->lookup(&config, "Setting_List")) == NULL || config_setting_type(t) != CONFIG_TYPE_LIST
			|| config_setting_is_group(t) || config_setting_is_array(t) || !config_setting_is_list(t)
			|| !config_setting_is_aggregate(t) || config_setting_is_scalar(t) || config_setting_is_number(t)
	) {
		libconfig->destroy(&config);
		return "CONFIG_TYPE_LIST failed.";
	}

	libconfig->destroy(&config);

	return NULL;
}
Example #6
0
/* Will validate the data retrieved from the configuration file */
int init(void) {
    int status;
    config_setting_t *conf_setting = NULL;
    const char *conf_value = NULL;
    
    /* Now the configuration file is read, we don't need to know the location
     * of the application anymore. We'll change working directory to root */
    if(chdir("/") < 0) {
        syslog(LOG_ERR, "Unable to change working directory to root: %s", strerror(errno));
        return EXIT_FAILURE;
    }
    
    syslog(LOG_INFO, "Checking presence and validity of required variables:");
    
    validateConfigBool(&config, "sync_2way", &common_data.sync_2way, 0);
    
    validateConfigBool(&config, "diff_commands", &common_data.diff_commands, 0);
    
    common_data.send_query = config_lookup(&config, "query") ? 1:0;
    if(common_data.send_query && ((conf_setting = config_lookup(&config, "query.trigger")) == NULL || 
    config_setting_is_array(conf_setting) == CONFIG_FALSE ||  (common_data.statusQueryLength = 
    config_setting_length(conf_setting)) == 0)) {
        syslog(LOG_ERR, "[ERROR] Setting is not present or not formatted as array: query.trigger");
        return EXIT_FAILURE;
    }
    if(common_data.send_query && validateConfigInt(&config, "query.interval", 
    &common_data.statusQueryInterval, -1, 0, 255, -1) == EXIT_FAILURE)
        return EXIT_FAILURE;
    
    /* Set volume (curve) functions */
    conf_value = NULL;
    config_lookup_string(&config, "volume.curve", &conf_value);
    if(!(common_data.volume = getVolume(&conf_value))) {
        syslog(LOG_ERR, "[Error] Volume curve is not recognised: %s", conf_value);
        return EXIT_FAILURE;
    }
    else {
        syslog(LOG_INFO, "[OK] volume.curve: %s", conf_value);
    }
    /* initialise volume variables */
    if(common_data.volume->init() == EXIT_FAILURE)
        return EXIT_FAILURE;
    
    /* Set and initialise process type */
    conf_value = NULL;
    config_lookup_string(&config, "data_type", &conf_value);
    if(!(common_data.process = getProcessMethod(&conf_value))) {
        syslog(LOG_ERR, "[Error] Setting 'data_type' is not recognised: %s", conf_value);
        return EXIT_FAILURE;
    }
    else {
        syslog(LOG_INFO, "[OK] data_type: %s", conf_value);
    }
    if(common_data.process->init() == EXIT_FAILURE)
        return EXIT_FAILURE;
    
    /* Set and initialise communication interface */
    conf_value = NULL;
    config_lookup_string(&config, "interface", &conf_value);
    if(!(common_data.interface = getInterface(&conf_value))) {
        syslog(LOG_ERR, "[Error] Setting 'interface' is not recognised: %s", conf_value);
        return EXIT_FAILURE;
    }
    else {
        syslog(LOG_INFO, "[OK] interface: %s", conf_value);
    }
    if(common_data.interface->init() == EXIT_FAILURE)
        return EXIT_FAILURE;
        
    /* initialise mixer device */
    if(initMixer() == EXIT_FAILURE)
        return EXIT_FAILURE;

    /* init multipliers */
    common_data.volume->regenerateMultipliers();

#ifndef DISABLE_MSQ
    /* initialise message queue */
    if(initMsQ() == EXIT_FAILURE)
        return EXIT_FAILURE;
#endif
    
    if((status = pthread_mutex_init(&lockConfig, NULL)) != 0) {
        syslog(LOG_ERR, "Failed to create config mutex: %i", status);
        return EXIT_FAILURE;
    }
    
    return EXIT_SUCCESS;
} /* end init */
Example #7
0
void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int *tcp_relay_port_count)
{
    const char *NAME_TCP_RELAY_PORTS = "tcp_relay_ports";

    *tcp_relay_port_count = 0;

    config_setting_t *ports_array = config_lookup(cfg, NAME_TCP_RELAY_PORTS);

    if (ports_array == NULL) {
        syslog(LOG_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS);
        syslog(LOG_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS);

        uint16_t default_ports[DEFAULT_TCP_RELAY_PORTS_COUNT] = {DEFAULT_TCP_RELAY_PORTS};

        int i;

        for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) {
            syslog(LOG_WARNING, "Port #%d: %u\n", i, default_ports[i]);
        }

        // similar procedure to the one of reading config file below
        *tcp_relay_ports = malloc(DEFAULT_TCP_RELAY_PORTS_COUNT * sizeof(uint16_t));

        for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) {

            (*tcp_relay_ports)[*tcp_relay_port_count] = default_ports[i];

            if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT
                    || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) {
                syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i,
                       (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT);
                continue;
            }

            (*tcp_relay_port_count) ++;
        }

        // the loop above skips invalid ports, so we adjust the allocated memory size
        if ((*tcp_relay_port_count) > 0) {
            *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
        } else {
            free(*tcp_relay_ports);
            *tcp_relay_ports = NULL;
        }

        return;
    }

    if (config_setting_is_array(ports_array) == CONFIG_FALSE) {
        syslog(LOG_WARNING, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n",
               NAME_TCP_RELAY_PORTS);
        return;
    }

    int config_port_count = config_setting_length(ports_array);

    if (config_port_count == 0) {
        syslog(LOG_WARNING, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS);
        return;
    }

    *tcp_relay_ports = malloc(config_port_count * sizeof(uint16_t));

    int i;

    for (i = 0; i < config_port_count; i ++) {
        config_setting_t *elem = config_setting_get_elem(ports_array, i);

        if (elem == NULL) {
            // it's NULL if `ports_array` is not an array (we have that check earlier) or if `i` is out of range, which should not be
            syslog(LOG_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i);
            break;
        }

        if (config_setting_is_number(elem) == CONFIG_FALSE) {
            syslog(LOG_WARNING, "Port #%d: Not a number. Skipping.\n", i);
            continue;
        }

        (*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem);

        if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT
                || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) {
            syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i,
                   (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT);
            continue;
        }

        (*tcp_relay_port_count) ++;
    }

    // the loop above skips invalid ports, so we adjust the allocated memory size
    if ((*tcp_relay_port_count) > 0) {
        *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
    } else {
        free(*tcp_relay_ports);
        *tcp_relay_ports = NULL;
    }
}