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:
Jouni Malinen 2010-07-18 14:30:24 -07:00 committed by Jouni Malinen
parent fdc9eeb175
commit 121adf9c2e
3 changed files with 236 additions and 233 deletions

View file

@ -15,6 +15,7 @@
#include "includes.h" #include "includes.h"
#include "common.h" #include "common.h"
#include "utils/uuid.h"
#include "crypto/sha1.h" #include "crypto/sha1.h"
#include "rsn_supp/wpa.h" #include "rsn_supp/wpa.h"
#include "eap_peer/eap.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 */ #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;
}

View file

@ -384,6 +384,10 @@ void wpa_config_debug_dump_networks(struct wpa_config *config);
#endif /* CONFIG_NO_STDOUT_DEBUG */ #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 */ /* Prototypes for backend specific functions from the selected config_*.c */
/** /**

View file

@ -22,7 +22,6 @@
#include "config.h" #include "config.h"
#include "base64.h" #include "base64.h"
#include "uuid.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 */ #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) struct wpa_config * wpa_config_read(const char *name)
{ {
FILE *f; FILE *f;