* @config: Pointer to global configuration data
* @pos: Name and value in the format "{name}={value}"
* @line: Line number in configuration file or 0 if not used
+ * @show_details: Whether to show parsing errors and other details in debug log
* Returns: 0 on success with a possible change in value, 1 on success with no
* change to previously configured value, or -1 on failure
*
* parameter must be in the same format as the text-based configuration file is
* using. For example, strings are using double quotation marks.
*/
-int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
+int wpa_config_process_global(struct wpa_config *config, char *pos, int line,
+ bool show_details)
{
size_t i;
int ret = 0;
ret = field->parser(field, config, line, pos + flen + 1);
if (ret < 0) {
- wpa_printf(MSG_ERROR, "Line %d: failed to "
- "parse '%s'.", line, pos);
+ if (show_details)
+ wpa_printf(MSG_ERROR,
+ "Line %d: failed to parse '%s'.",
+ line, pos);
ret = -1;
}
if (ret == 1)
char *tmp = os_strchr(pos, '=');
if (!tmp) {
- if (line < 0)
+ if (show_details)
wpa_printf(MSG_ERROR,
"Line %d: invalid line %s",
line, pos);
*tmp++ = '\0';
if (hostapd_config_tx_queue(config->tx_queue, pos,
tmp)) {
- wpa_printf(MSG_ERROR,
- "Line %d: invalid TX queue item",
- line);
+ if (show_details)
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid TX queue item",
+ line);
return -1;
}
return ret;
if (tmp == NULL) {
if (line < 0)
return -1;
- wpa_printf(MSG_ERROR, "Line %d: invalid line "
- "'%s'", line, pos);
+ if (show_details)
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid line '%s'",
+ line, pos);
return -1;
}
*tmp++ = '\0';
if (hostapd_config_wmm_ac(config->wmm_ac_params, pos,
tmp)) {
- wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
- "AC item", line);
+ if (show_details)
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid WMM AC item",
+ line);
return -1;
}
return ret;
#endif /* CONFIG_AP */
if (line < 0)
return -1;
- wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
- line, pos);
+ if (show_details)
+ wpa_printf(MSG_ERROR,
+ "Line %d: unknown global field '%s'.",
+ line, pos);
ret = -1;
}
/* Prototypes for common functions from config.c */
-int wpa_config_process_global(struct wpa_config *config, char *pos, int line);
+int wpa_config_process_global(struct wpa_config *config, char *pos, int line,
+ bool show_details);
int wpa_config_get_num_global_field_names(void);
* configuration file)
* @cfgp: Pointer to previously allocated configuration data or %NULL if none
* @ro: Whether to mark networks from this configuration as read-only
+ * @show_details: Whether to show parsing errors and other details in debug log
* Returns: Pointer to allocated configuration data or %NULL on failure
*
* This function reads configuration data, parses its contents, and allocates
* Each configuration backend needs to implement this function.
*/
struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
- bool ro);
+ bool ro, bool show_details);
/**
* wpa_config_write - Write or update configuration data
struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
- bool ro)
+ bool ro, bool show_details)
{
FILE *f;
char buf[1024], *pos;
wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
f = fopen(name, "r");
if (f == NULL) {
- wpa_printf(MSG_ERROR, "Failed to open config file '%s', "
- "error: %s", name, strerror(errno));
+ if (show_details)
+ wpa_printf(MSG_ERROR,
+ "Failed to open config file '%s', error: %s",
+ name, strerror(errno));
if (config != cfgp)
os_free(config);
return NULL;
}
while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {
+#ifndef WPA_IGNORE_CONFIG_ERRORS
+ if (errors && !show_details)
+ break;
+#endif /* WPA_IGNORE_CONFIG_ERRORS */
+
if (os_strcmp(pos, "network={") == 0) {
ssid = wpa_config_read_network(f, &line, id++);
if (ssid == NULL) {
identity_tail->next = identity;
identity_tail = identity;
}
- } else if (wpa_config_process_global(config, pos, line) < 0) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "
- "line '%s'.", line, pos);
+ } else if (wpa_config_process_global(config, pos, line,
+ show_details) < 0) {
+ if (show_details)
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid configuration line '%s'.",
+ line, pos);
errors++;
continue;
}
struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
- bool ro)
+ bool ro, bool show_details)
{
struct wpa_config *config;
struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
- bool ro)
+ bool ro, bool show_details)
{
TCHAR buf[256];
int errors = 0;
ret = -1;
} else {
value[-1] = '=';
- wpa_config_process_global(wpa_s->conf, cmd, -1);
+ wpa_config_process_global(wpa_s->conf, cmd, -1,
+ true);
}
} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
0) {
ret = -1;
} else {
value[-1] = '=';
- wpa_config_process_global(wpa_s->conf, cmd, -1);
+ wpa_config_process_global(wpa_s->conf, cmd, -1,
+ true);
}
} else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
ret = -1;
} else {
value[-1] = '=';
- wpa_config_process_global(wpa_s->conf, cmd, -1);
+ wpa_config_process_global(wpa_s->conf, cmd, -1,
+ true);
}
} else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
wpa_s->wps_fragment_size = atoi(value);
ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
if (ret == 0) {
value[-1] = '=';
- wpa_config_process_global(wpa_s->conf, cmd, -1);
+ wpa_config_process_global(wpa_s->conf, cmd, -1,
+ true);
}
} else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
int val = atoi(value);
#endif /* CONFIG_PASN */
} else {
value[-1] = '=';
- ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
+ ret = wpa_config_process_global(
+ wpa_s->conf, cmd, -1,
+ wpa_s->global->params.show_details);
if (ret == 0)
wpa_supplicant_update_config(wpa_s);
else if (ret == 1)
return FALSE;
}
- ret = wpa_config_process_global(wpa_s->conf, buf, -1);
+ ret = wpa_config_process_global(wpa_s->conf, buf, -1, false);
if (ret < 0) {
dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
"Failed to set interface property %s",
dl_list_init(&wpa_s.bss);
dl_list_init(&wpa_s.bss_id);
if (conf)
- wpa_s.conf = wpa_config_read(conf, NULL, false);
+ wpa_s.conf = wpa_config_read(conf, NULL, false, true);
else
wpa_s.conf = wpa_config_alloc_empty(ctrl_iface, NULL);
if (wpa_s.conf == NULL) {
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
"u"
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
- "vW] [-P<pid file>] "
+ "vWy] [-P<pid file>] "
"[-g<global ctrl>] \\\n"
" [-G<group>] \\\n"
- " -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
+ " [-i<ifname>] -c<config file> [-C<ctrl>] [-D<driver>] "
"[-p<driver_param>] \\\n"
" [-b<br_ifname>] [-e<entropy file>]"
#ifdef CONFIG_DEBUG_FILE
" -u = enable DBus control interface\n"
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
" -v = show version\n"
- " -W = wait for a control interface monitor before starting\n");
+ " -W = wait for a control interface monitor before starting\n"
+ " -y = show configuration parsing details in debug log\n");
printf("example:\n"
" wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n",
wpa_drivers[0] ? wpa_drivers[0]->name : "nl80211");
+ printf("\nIf run without specifying a network interface or control interface, the a\n"
+ "configuration file is parsed without starting any operation.\n"
+ "This can be used to check whether a configuration file has valid contents.\n");
#endif /* CONFIG_NO_STDOUT_DEBUG */
}
for (;;) {
c = getopt(argc, argv,
- "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
+ "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvWy");
if (c < 0)
break;
switch (c) {
iface = &ifaces[iface_count - 1];
os_memset(iface, 0, sizeof(*iface));
break;
+ case 'y':
+ params.show_details = true;
+ break;
default:
usage();
exitcode = 0;
wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant");
exitcode = -1;
goto out;
- } else {
- wpa_printf(MSG_INFO, "Successfully initialized "
- "wpa_supplicant");
}
+ if (iface_count == 1 && ifaces[0].confname && !ifaces[0].ifname &&
+#ifdef CONFIG_MATCH_IFACE
+ !params.match_iface_count &&
+#endif /* CONFIG_MATCH_IFACE */
+ !ifaces[0].ctrl_interface && !params.dbus_ctrl_interface) {
+ exitcode = wpa_supplicant_parse_config(ifaces[0].confname);
+ wpa_supplicant_deinit(global);
+ goto out;
+ }
+
+ wpa_printf(MSG_INFO, "Successfully initialized wpa_supplicant");
+
if (fst_global_init()) {
wpa_printf(MSG_ERROR, "Failed to initialize FST");
+ wpa_supplicant_deinit(global);
exitcode = -1;
goto out;
}
}
os_memset(&wpa_s, 0, sizeof(wpa_s));
- wpa_s.conf = wpa_config_read(argv[1], NULL, false);
+ wpa_s.conf = wpa_config_read(argv[1], NULL, false, true);
if (wpa_s.conf == NULL) {
printf("Failed to parse configuration file '%s'.\n", argv[1]);
return -1;
if (wpa_s->confname == NULL)
return -1;
- conf = wpa_config_read(wpa_s->confname, NULL, false);
+ conf = wpa_config_read(wpa_s->confname, NULL, false,
+ wpa_s->global->params.show_details);
if (conf == NULL) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
"file '%s' - exiting", wpa_s->confname);
return -1;
}
if (wpa_s->confanother &&
- !wpa_config_read(wpa_s->confanother, conf, true)) {
+ !wpa_config_read(wpa_s->confanother, conf, true,
+ wpa_s->global->params.show_details)) {
wpa_msg(wpa_s, MSG_ERROR,
"Failed to parse the configuration file '%s' - exiting",
wpa_s->confanother);
#else /* CONFIG_BACKEND_FILE */
wpa_s->confname = os_strdup(iface->confname);
#endif /* CONFIG_BACKEND_FILE */
- wpa_s->conf = wpa_config_read(wpa_s->confname, NULL, false);
+ wpa_s->conf = wpa_config_read(
+ wpa_s->confname, NULL, false,
+ wpa_s->global->params.show_details);
if (wpa_s->conf == NULL) {
wpa_printf(MSG_ERROR, "Failed to read or parse "
"configuration '%s'.", wpa_s->confname);
}
wpa_s->confanother = os_rel2abs_path(iface->confanother);
if (wpa_s->confanother &&
- !wpa_config_read(wpa_s->confanother, wpa_s->conf, true)) {
+ !wpa_config_read(wpa_s->confanother, wpa_s->conf, true,
+ wpa_s->global->params.show_details)) {
wpa_printf(MSG_ERROR,
"Failed to read or parse configuration '%s'.",
wpa_s->confanother);
global->params.daemonize = params->daemonize;
global->params.wait_for_monitor = params->wait_for_monitor;
global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
+ global->params.show_details = params->show_details;
if (params->pid_file) {
global->params.pid_file = os_strdup(params->pid_file);
}
+int wpa_supplicant_parse_config(const char *fname)
+{
+ struct wpa_config *conf;
+ int ret = -1;
+
+ wpa_printf(MSG_INFO, "Validating parsing of %s", fname);
+ conf = wpa_config_read(fname, NULL, false, true);
+ if (conf) {
+ wpa_printf(MSG_INFO, "Parsing succeeded");
+ ret = 0;
+ wpa_config_free(conf);
+ } else {
+ wpa_printf(MSG_INFO, "Parsing failed");
+ }
+ return ret;
+}
+
+
void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
{
if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
*/
int match_iface_count;
#endif /* CONFIG_MATCH_IFACE */
+
+ /**
+ * show_details - Whether to show config parsing details in debug log
+ */
+ bool show_details;
};
struct p2p_srv_bonjour {
struct wpa_global * wpa_supplicant_init(struct wpa_params *params);
int wpa_supplicant_run(struct wpa_global *global);
void wpa_supplicant_deinit(struct wpa_global *global);
+int wpa_supplicant_parse_config(const char *fname);
int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);