Move global configuration parser into config.c
This makes it easier to provide support for dynamic updates of the global configuration parameters while wpa_supplicant is running.
This commit is contained in:
parent
fdc9eeb175
commit
121adf9c2e
3 changed files with 236 additions and 233 deletions
|
@ -15,6 +15,7 @@
|
|||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "utils/uuid.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "rsn_supp/wpa.h"
|
||||
#include "eap_peer/eap.h"
|
||||
|
@ -2165,3 +2166,234 @@ void wpa_config_debug_dump_networks(struct wpa_config *config)
|
|||
}
|
||||
}
|
||||
#endif /* CONFIG_NO_STDOUT_DEBUG */
|
||||
|
||||
|
||||
struct global_parse_data {
|
||||
char *name;
|
||||
int (*parser)(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line, const char *value);
|
||||
void *param1, *param2, *param3;
|
||||
};
|
||||
|
||||
|
||||
static int wpa_global_config_parse_int(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line,
|
||||
const char *pos)
|
||||
{
|
||||
int *dst;
|
||||
dst = (int *) (((u8 *) config) + (long) data->param1);
|
||||
*dst = atoi(pos);
|
||||
wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
|
||||
|
||||
if (data->param2 && *dst < (long) data->param2) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
|
||||
"min_value=%ld)", line, data->name, *dst,
|
||||
(long) data->param2);
|
||||
*dst = (long) data->param2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data->param3 && *dst > (long) data->param3) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
|
||||
"max_value=%ld)", line, data->name, *dst,
|
||||
(long) data->param3);
|
||||
*dst = (long) data->param3;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_global_config_parse_str(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line,
|
||||
const char *pos)
|
||||
{
|
||||
size_t len;
|
||||
char **dst, *tmp;
|
||||
|
||||
len = os_strlen(pos);
|
||||
if (data->param2 && len < (size_t) data->param2) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
|
||||
"min_len=%ld)", line, data->name,
|
||||
(unsigned long) len, (long) data->param2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data->param3 && len > (size_t) data->param3) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
|
||||
"max_len=%ld)", line, data->name,
|
||||
(unsigned long) len, (long) data->param3);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = os_strdup(pos);
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
|
||||
dst = (char **) (((u8 *) config) + (long) data->param1);
|
||||
os_free(*dst);
|
||||
*dst = tmp;
|
||||
wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_config_process_country(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line,
|
||||
const char *pos)
|
||||
{
|
||||
if (!pos[0] || !pos[1]) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid country set");
|
||||
return -1;
|
||||
}
|
||||
config->country[0] = pos[0];
|
||||
config->country[1] = pos[1];
|
||||
wpa_printf(MSG_DEBUG, "country='%c%c'",
|
||||
config->country[0], config->country[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_config_process_load_dynamic_eap(
|
||||
const struct global_parse_data *data, struct wpa_config *config,
|
||||
int line, const char *so)
|
||||
{
|
||||
int ret;
|
||||
wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
|
||||
ret = eap_peer_method_load(so);
|
||||
if (ret == -2) {
|
||||
wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
|
||||
"reloading.");
|
||||
} else if (ret) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
|
||||
"method '%s'.", line, so);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
|
||||
static int wpa_config_process_uuid(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line,
|
||||
const char *pos)
|
||||
{
|
||||
char buf[40];
|
||||
if (uuid_str2bin(pos, config->uuid)) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
|
||||
return -1;
|
||||
}
|
||||
uuid_bin2str(config->uuid, buf, sizeof(buf));
|
||||
wpa_printf(MSG_DEBUG, "uuid=%s", buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_config_process_os_version(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line,
|
||||
const char *pos)
|
||||
{
|
||||
if (hexstr2bin(pos, config->os_version, 4)) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
|
||||
return -1;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "os_version=%08x",
|
||||
WPA_GET_BE32(config->os_version));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
|
||||
#ifdef OFFSET
|
||||
#undef OFFSET
|
||||
#endif /* OFFSET */
|
||||
/* OFFSET: Get offset of a variable within the wpa_config structure */
|
||||
#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
|
||||
|
||||
#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
|
||||
#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
|
||||
#define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f)
|
||||
#define INT(f) _INT(f), NULL, NULL
|
||||
#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
|
||||
#define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f)
|
||||
#define STR(f) _STR(f), NULL, NULL
|
||||
#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
|
||||
|
||||
static const struct global_parse_data global_fields[] = {
|
||||
#ifdef CONFIG_CTRL_IFACE
|
||||
{ STR(ctrl_interface) },
|
||||
{ STR(ctrl_interface_group) } /* deprecated */,
|
||||
#endif /* CONFIG_CTRL_IFACE */
|
||||
{ INT_RANGE(eapol_version, 1, 2) },
|
||||
{ INT(ap_scan) },
|
||||
{ INT(fast_reauth) },
|
||||
{ STR(opensc_engine_path) },
|
||||
{ STR(pkcs11_engine_path) },
|
||||
{ STR(pkcs11_module_path) },
|
||||
{ STR(driver_param) },
|
||||
{ INT(dot11RSNAConfigPMKLifetime) },
|
||||
{ INT(dot11RSNAConfigPMKReauthThreshold) },
|
||||
{ INT(dot11RSNAConfigSATimeout) },
|
||||
#ifndef CONFIG_NO_CONFIG_WRITE
|
||||
{ INT(update_config) },
|
||||
#endif /* CONFIG_NO_CONFIG_WRITE */
|
||||
{ FUNC_NO_VAR(load_dynamic_eap) },
|
||||
#ifdef CONFIG_WPS
|
||||
{ FUNC(uuid) },
|
||||
{ STR_RANGE(device_name, 0, 32) },
|
||||
{ STR_RANGE(manufacturer, 0, 64) },
|
||||
{ STR_RANGE(model_name, 0, 32) },
|
||||
{ STR_RANGE(model_number, 0, 32) },
|
||||
{ STR_RANGE(serial_number, 0, 32) },
|
||||
{ STR(device_type) },
|
||||
{ FUNC(os_version) },
|
||||
{ STR(config_methods) },
|
||||
{ INT_RANGE(wps_cred_processing, 0, 2) },
|
||||
#endif /* CONFIG_WPS */
|
||||
{ FUNC(country) },
|
||||
{ INT(bss_max_count) },
|
||||
{ INT_RANGE(filter_ssids, 0, 1) }
|
||||
};
|
||||
|
||||
#undef FUNC
|
||||
#undef _INT
|
||||
#undef INT
|
||||
#undef INT_RANGE
|
||||
#undef _STR
|
||||
#undef STR
|
||||
#undef STR_RANGE
|
||||
#define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0]))
|
||||
|
||||
|
||||
int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
|
||||
{
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
|
||||
const struct global_parse_data *field = &global_fields[i];
|
||||
size_t flen = os_strlen(field->name);
|
||||
if (os_strncmp(pos, field->name, flen) != 0 ||
|
||||
pos[flen] != '=')
|
||||
continue;
|
||||
|
||||
if (field->parser(field, config, line, pos + flen + 1)) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: failed to "
|
||||
"parse '%s'.", line, pos);
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (i == NUM_GLOBAL_FIELDS) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
|
||||
line, pos);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -384,6 +384,10 @@ void wpa_config_debug_dump_networks(struct wpa_config *config);
|
|||
#endif /* CONFIG_NO_STDOUT_DEBUG */
|
||||
|
||||
|
||||
/* Prototypes for common functions from config.c */
|
||||
int wpa_config_process_global(struct wpa_config *config, char *pos, int line);
|
||||
|
||||
|
||||
/* Prototypes for backend specific functions from the selected config_*.c */
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "config.h"
|
||||
#include "base64.h"
|
||||
#include "uuid.h"
|
||||
#include "eap_peer/eap_methods.h"
|
||||
|
||||
|
||||
/**
|
||||
|
@ -270,238 +269,6 @@ static int wpa_config_process_blob(struct wpa_config *config, FILE *f,
|
|||
#endif /* CONFIG_NO_CONFIG_BLOBS */
|
||||
|
||||
|
||||
struct global_parse_data {
|
||||
char *name;
|
||||
int (*parser)(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line, const char *value);
|
||||
void *param1, *param2, *param3;
|
||||
};
|
||||
|
||||
|
||||
static int wpa_config_parse_int(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line,
|
||||
const char *pos)
|
||||
{
|
||||
int *dst;
|
||||
dst = (int *) (((u8 *) config) + (long) data->param1);
|
||||
*dst = atoi(pos);
|
||||
wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
|
||||
|
||||
if (data->param2 && *dst < (long) data->param2) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
|
||||
"min_value=%ld)", line, data->name, *dst,
|
||||
(long) data->param2);
|
||||
*dst = (long) data->param2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data->param3 && *dst > (long) data->param3) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
|
||||
"max_value=%ld)", line, data->name, *dst,
|
||||
(long) data->param3);
|
||||
*dst = (long) data->param3;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_config_parse_str(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line,
|
||||
const char *pos)
|
||||
{
|
||||
size_t len;
|
||||
char **dst, *tmp;
|
||||
|
||||
len = os_strlen(pos);
|
||||
if (data->param2 && len < (size_t) data->param2) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
|
||||
"min_len=%ld)", line, data->name,
|
||||
(unsigned long) len, (long) data->param2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data->param3 && len > (size_t) data->param3) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
|
||||
"max_len=%ld)", line, data->name,
|
||||
(unsigned long) len, (long) data->param3);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = os_strdup(pos);
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
|
||||
dst = (char **) (((u8 *) config) + (long) data->param1);
|
||||
os_free(*dst);
|
||||
*dst = tmp;
|
||||
wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_config_process_country(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line,
|
||||
const char *pos)
|
||||
{
|
||||
if (!pos[0] || !pos[1]) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid country set");
|
||||
return -1;
|
||||
}
|
||||
config->country[0] = pos[0];
|
||||
config->country[1] = pos[1];
|
||||
wpa_printf(MSG_DEBUG, "country='%c%c'",
|
||||
config->country[0], config->country[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_config_process_load_dynamic_eap(
|
||||
const struct global_parse_data *data, struct wpa_config *config,
|
||||
int line, const char *so)
|
||||
{
|
||||
int ret;
|
||||
wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
|
||||
ret = eap_peer_method_load(so);
|
||||
if (ret == -2) {
|
||||
wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
|
||||
"reloading.");
|
||||
} else if (ret) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
|
||||
"method '%s'.", line, so);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
|
||||
static int wpa_config_process_uuid(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line,
|
||||
const char *pos)
|
||||
{
|
||||
char buf[40];
|
||||
if (uuid_str2bin(pos, config->uuid)) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
|
||||
return -1;
|
||||
}
|
||||
uuid_bin2str(config->uuid, buf, sizeof(buf));
|
||||
wpa_printf(MSG_DEBUG, "uuid=%s", buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_config_process_os_version(const struct global_parse_data *data,
|
||||
struct wpa_config *config, int line,
|
||||
const char *pos)
|
||||
{
|
||||
if (hexstr2bin(pos, config->os_version, 4)) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
|
||||
return -1;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "os_version=%08x",
|
||||
WPA_GET_BE32(config->os_version));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
|
||||
#ifdef OFFSET
|
||||
#undef OFFSET
|
||||
#endif /* OFFSET */
|
||||
/* OFFSET: Get offset of a variable within the wpa_config structure */
|
||||
#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
|
||||
|
||||
#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
|
||||
#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
|
||||
#define _INT(f) #f, wpa_config_parse_int, OFFSET(f)
|
||||
#define INT(f) _INT(f), NULL, NULL
|
||||
#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
|
||||
#define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
|
||||
#define STR(f) _STR(f), NULL, NULL
|
||||
#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
|
||||
|
||||
static const struct global_parse_data global_fields[] = {
|
||||
#ifdef CONFIG_CTRL_IFACE
|
||||
{ STR(ctrl_interface) },
|
||||
{ STR(ctrl_interface_group) } /* deprecated */,
|
||||
#endif /* CONFIG_CTRL_IFACE */
|
||||
{ INT_RANGE(eapol_version, 1, 2) },
|
||||
{ INT(ap_scan) },
|
||||
{ INT(fast_reauth) },
|
||||
{ STR(opensc_engine_path) },
|
||||
{ STR(pkcs11_engine_path) },
|
||||
{ STR(pkcs11_module_path) },
|
||||
{ STR(driver_param) },
|
||||
{ INT(dot11RSNAConfigPMKLifetime) },
|
||||
{ INT(dot11RSNAConfigPMKReauthThreshold) },
|
||||
{ INT(dot11RSNAConfigSATimeout) },
|
||||
#ifndef CONFIG_NO_CONFIG_WRITE
|
||||
{ INT(update_config) },
|
||||
#endif /* CONFIG_NO_CONFIG_WRITE */
|
||||
{ FUNC_NO_VAR(load_dynamic_eap) },
|
||||
#ifdef CONFIG_WPS
|
||||
{ FUNC(uuid) },
|
||||
{ STR_RANGE(device_name, 0, 32) },
|
||||
{ STR_RANGE(manufacturer, 0, 64) },
|
||||
{ STR_RANGE(model_name, 0, 32) },
|
||||
{ STR_RANGE(model_number, 0, 32) },
|
||||
{ STR_RANGE(serial_number, 0, 32) },
|
||||
{ STR(device_type) },
|
||||
{ FUNC(os_version) },
|
||||
{ STR(config_methods) },
|
||||
{ INT_RANGE(wps_cred_processing, 0, 2) },
|
||||
#endif /* CONFIG_WPS */
|
||||
{ FUNC(country) },
|
||||
{ INT(bss_max_count) },
|
||||
{ INT_RANGE(filter_ssids, 0, 1) }
|
||||
};
|
||||
|
||||
#undef FUNC
|
||||
#undef _INT
|
||||
#undef INT
|
||||
#undef INT_RANGE
|
||||
#undef _STR
|
||||
#undef STR
|
||||
#undef STR_RANGE
|
||||
#define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0]))
|
||||
|
||||
|
||||
static int wpa_config_process_global(struct wpa_config *config, char *pos,
|
||||
int line)
|
||||
{
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
|
||||
const struct global_parse_data *field = &global_fields[i];
|
||||
size_t flen = os_strlen(field->name);
|
||||
if (os_strncmp(pos, field->name, flen) != 0 ||
|
||||
pos[flen] != '=')
|
||||
continue;
|
||||
|
||||
if (field->parser(field, config, line, pos + flen + 1)) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: failed to "
|
||||
"parse '%s'.", line, pos);
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (i == NUM_GLOBAL_FIELDS) {
|
||||
wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
|
||||
line, pos);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct wpa_config * wpa_config_read(const char *name)
|
||||
{
|
||||
FILE *f;
|
||||
|
|
Loading…
Reference in a new issue