1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant / Configuration backend: text file
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This file implements a configuration backend for text files. All the
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * configuration information is stored in a text file that uses a format
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * described in the sample configuration file, wpa_supplicant.conf.
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "config.h"
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "base64.h"
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "uuid.h"
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_peer/eap_methods.h"
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/**
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * wpa_config_get_line - Read the next configuration file line
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @s: Buffer for the line
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @size: The buffer length
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @stream: File stream to read from
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @line: Pointer to a variable storing the file line number
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @_pos: Buffer for the pointer to the beginning of data on the text line or
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * %NULL if not needed (returned value used instead)
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: Pointer to the beginning of data on the text line or %NULL if no
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * more text lines are available.
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This function reads the next non-empty line from the configuration file and
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * removes comments. The returned string is guaranteed to be null-terminated.
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic char * wpa_config_get_line(char *s, int size, FILE *stream, int *line,
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  char **_pos)
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *pos, *end, *sstart;
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (fgets(s, size, stream)) {
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		(*line)++;
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		s[size - 1] = '\0';
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos = s;
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* Skip white space from the beginning of line. */
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		while (*pos == ' ' || *pos == '\t' || *pos == '\r')
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			pos++;
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* Skip comment lines and empty lines */
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*pos == '#' || *pos == '\n' || *pos == '\0')
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/*
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * Remove # comments unless they are within a double quoted
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * string.
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 */
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		sstart = os_strchr(pos, '"');
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (sstart)
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sstart = os_strrchr(sstart + 1, '"');
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (!sstart)
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sstart = pos;
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		end = os_strchr(sstart, '#');
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (end)
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*end-- = '\0';
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		else
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			end = pos + os_strlen(pos) - 1;
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* Remove trailing white space. */
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		while (end > pos &&
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		       (*end == '\n' || *end == ' ' || *end == '\t' ||
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*end == '\r'))
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*end-- = '\0';
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*pos == '\0')
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (_pos)
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*_pos = pos;
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return pos;
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (_pos)
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*_pos = NULL;
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return NULL;
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int errors = 0;
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->passphrase) {
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ssid->psk_set) {
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: both PSK and "
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "passphrase configured.", line);
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_update_psk(ssid);
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       WPA_KEY_MGMT_PSK_SHA256)) &&
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !ssid->psk_set) {
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key "
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "management, but no PSK configured.", line);
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		errors++;
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) {
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* Group cipher cannot be stronger than the pairwise cipher. */
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher"
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   " list since it was not allowed for pairwise "
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "cipher", line);
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ssid->group_cipher &= ~WPA_CIPHER_CCMP;
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return errors;
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id)
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ssid *ssid;
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int errors = 0, end = 0;
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char buf[256], *pos, *pos2;
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block",
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   *line);
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ssid = os_zalloc(sizeof(*ssid));
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid == NULL)
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ssid->id = id;
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_set_network_defaults(ssid);
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (os_strcmp(pos, "}") == 0) {
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			end = 1;
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos2 = os_strchr(pos, '=');
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (pos2 == NULL) {
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line "
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "'%s'.", *line, pos);
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos2++ = '\0';
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*pos2 == '"') {
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (os_strchr(pos2 + 1, '"') == NULL) {
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				wpa_printf(MSG_ERROR, "Line %d: invalid "
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   "quotation '%s'.", *line, pos2);
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				errors++;
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				continue;
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			}
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (wpa_config_set(ssid, pos, pos2, *line) < 0)
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!end) {
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: network block was not "
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "terminated properly.", *line);
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		errors++;
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	errors += wpa_config_validate_network(ssid, *line);
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (errors) {
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_free_ssid(ssid);
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ssid = NULL;
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ssid;
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line,
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						     const char *name)
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_config_blob *blob;
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char buf[256], *pos;
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	unsigned char *encoded = NULL, *nencoded;
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int end = 0;
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t encoded_len = 0, len;
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new named blob '%s'",
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   *line, name);
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (os_strcmp(pos, "}") == 0) {
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			end = 1;
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		len = os_strlen(pos);
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		nencoded = os_realloc(encoded, encoded_len + len);
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (nencoded == NULL) {
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: not enough memory for "
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "blob", *line);
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(encoded);
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return NULL;
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		encoded = nencoded;
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(encoded + encoded_len, pos, len);
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		encoded_len += len;
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!end) {
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: blob was not terminated "
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "properly", *line);
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(encoded);
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	blob = os_zalloc(sizeof(*blob));
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (blob == NULL) {
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(encoded);
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	blob->name = os_strdup(name);
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	blob->data = base64_decode(encoded, encoded_len, &blob->len);
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(encoded);
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (blob->name == NULL || blob->data == NULL) {
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_free_blob(blob);
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return blob;
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_process_blob(struct wpa_config *config, FILE *f,
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   int *line, char *bname)
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *name_end;
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_config_blob *blob;
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	name_end = os_strchr(bname, '=');
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (name_end == NULL) {
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: no blob name terminator",
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   *line);
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*name_end = '\0';
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	blob = wpa_config_read_blob(f, line, bname);
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (blob == NULL) {
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: failed to read blob %s",
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   *line, bname);
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_set_blob(config, blob);
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct global_parse_data {
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *name;
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int (*parser)(const struct global_parse_data *data,
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		      struct wpa_config *config, int line, const char *value);
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	void *param1, *param2, *param3;
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_parse_int(const struct global_parse_data *data,
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				struct wpa_config *config, int line,
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				const char *pos)
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int *dst;
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst = (int *) (((u8 *) config) + (long) data->param1);
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*dst = atoi(pos);
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst);
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data->param2 && *dst < (long) data->param2) {
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "min_value=%ld)", line, data->name, *dst,
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (long) data->param2);
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*dst = (long) data->param2;
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data->param3 && *dst > (long) data->param3) {
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "max_value=%ld)", line, data->name, *dst,
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (long) data->param3);
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*dst = (long) data->param3;
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_parse_str(const struct global_parse_data *data,
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				struct wpa_config *config, int line,
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				const char *pos)
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t len;
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char **dst, *tmp;
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	len = os_strlen(pos);
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data->param2 && len < (size_t) data->param2) {
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "min_len=%ld)", line, data->name,
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned long) len, (long) data->param2);
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data->param3 && len > (size_t) data->param3) {
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "max_len=%ld)", line, data->name,
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned long) len, (long) data->param3);
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	tmp = os_strdup(pos);
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (tmp == NULL)
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	dst = (char **) (((u8 *) config) + (long) data->param1);
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(*dst);
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*dst = tmp;
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst);
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_process_country(const struct global_parse_data *data,
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				      struct wpa_config *config, int line,
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				      const char *pos)
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!pos[0] || !pos[1]) {
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Invalid country set");
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config->country[0] = pos[0];
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config->country[1] = pos[1];
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "country='%c%c'",
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   config->country[0], config->country[1]);
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_process_load_dynamic_eap(
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const struct global_parse_data *data, struct wpa_config *config,
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int line, const char *so)
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ret;
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = eap_peer_method_load(so);
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret == -2) {
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not "
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "reloading.");
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else if (ret) {
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP "
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "method '%s'.", line, so);
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_WPS
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_process_uuid(const struct global_parse_data *data,
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   struct wpa_config *config, int line,
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   const char *pos)
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char buf[40];
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (uuid_str2bin(pos, config->uuid)) {
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	uuid_bin2str(config->uuid, buf, sizeof(buf));
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "uuid=%s", buf);
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_process_os_version(const struct global_parse_data *data,
399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					 struct wpa_config *config, int line,
400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					 const char *pos)
401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (hexstr2bin(pos, config->os_version, 4)) {
403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: invalid os_version", line);
404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "os_version=%08x",
407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   WPA_GET_BE32(config->os_version));
408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_WPS */
412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef OFFSET
415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef OFFSET
416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* OFFSET */
417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* OFFSET: Get offset of a variable within the wpa_config structure */
418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define _INT(f) #f, wpa_config_parse_int, OFFSET(f)
423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define INT(f) _INT(f), NULL, NULL
424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define _STR(f) #f, wpa_config_parse_str, OFFSET(f)
426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define STR(f) _STR(f), NULL, NULL
427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const struct global_parse_data global_fields[] = {
430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE
431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR(ctrl_interface) },
432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR(ctrl_interface_group) } /* deprecated */,
433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ INT_RANGE(eapol_version, 1, 2) },
435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ INT(ap_scan) },
436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ INT(fast_reauth) },
437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef EAP_TLS_OPENSSL
438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR(opensc_engine_path) },
439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR(pkcs11_engine_path) },
440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR(pkcs11_module_path) },
441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* EAP_TLS_OPENSSL */
442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR(driver_param) },
443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ INT(dot11RSNAConfigPMKLifetime) },
444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ INT(dot11RSNAConfigPMKReauthThreshold) },
445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ INT(dot11RSNAConfigSATimeout) },
446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NO_CONFIG_WRITE
447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ INT(update_config) },
448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NO_CONFIG_WRITE */
449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ FUNC_NO_VAR(load_dynamic_eap) },
450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_WPS
451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ FUNC(uuid) },
452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR_RANGE(device_name, 0, 32) },
453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR_RANGE(manufacturer, 0, 64) },
454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR_RANGE(model_name, 0, 32) },
455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR_RANGE(model_number, 0, 32) },
456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR_RANGE(serial_number, 0, 32) },
457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ STR(device_type) },
458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ FUNC(os_version) },
459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ INT_RANGE(wps_cred_processing, 0, 2) },
460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_WPS */
461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	{ FUNC(country) }
462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef FUNC
465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef _INT
466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef INT
467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef INT_RANGE
468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef _STR
469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef STR
470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef STR_RANGE
471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define NUM_GLOBAL_FIELDS (sizeof(global_fields) / sizeof(global_fields[0]))
472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_process_global(struct wpa_config *config, char *pos,
475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				     int line)
476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t i;
478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ret = 0;
479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		const struct global_parse_data *field = &global_fields[i];
482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		size_t flen = os_strlen(field->name);
483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (os_strncmp(pos, field->name, flen) != 0 ||
484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    pos[flen] != '=')
485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (field->parser(field, config, line, pos + flen + 1)) {
488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: failed to "
489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "parse '%s'.", line, pos);
490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ret = -1;
491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (i == NUM_GLOBAL_FIELDS) {
495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.",
496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   line, pos);
497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ret = -1;
498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ret;
501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_config * wpa_config_read(const char *name)
505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	FILE *f;
507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char buf[256], *pos;
508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int errors = 0, line = 0;
509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_config *config;
511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int id = 0;
512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config = wpa_config_alloc_empty(NULL, NULL);
514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config == NULL)
515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	f = fopen(name, "r");
518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (f == NULL) {
519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(config);
520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {
524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (os_strcmp(pos, "network={") == 0) {
525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ssid = wpa_config_read_network(f, &line, id++);
526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (ssid == NULL) {
527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				wpa_printf(MSG_ERROR, "Line %d: failed to "
528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   "parse network block.", line);
5292c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifndef WPA_IGNORE_CONFIG_ERRORS
530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				errors++;
5312c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif
532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				continue;
533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			}
534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (head == NULL) {
535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				head = tail = ssid;
536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			} else {
537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				tail->next = ssid;
538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				tail = ssid;
539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			}
540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (wpa_config_add_prio_network(config, ssid)) {
541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				wpa_printf(MSG_ERROR, "Line %d: failed to add "
542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   "network block to priority list.",
543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   line);
544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				errors++;
545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				continue;
546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			}
547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else if (os_strncmp(pos, "blob-base64-", 12) == 0) {
549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (wpa_config_process_blob(config, f, &line, pos + 12)
550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    < 0) {
551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				errors++;
552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				continue;
553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			}
554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else if (wpa_config_process_global(config, pos, line) < 0) {
556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "
557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "line '%s'.", line, pos);
558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	fclose(f);
564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config->ssid = head;
566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_debug_dump_networks(config);
567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
5682c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#ifndef WPA_IGNORE_CONFIG_ERRORS
569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (errors) {
570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_free(config);
571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		config = NULL;
572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		head = NULL;
573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
5742c23b7348ac966c08728d4908cf89d673d91bb76Dmitry Shmidt#endif
575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return config;
577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NO_CONFIG_WRITE
581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_str(FILE *f, const char *field, struct wpa_ssid *ssid)
583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value = wpa_config_get(ssid, field);
585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	fprintf(f, "\t%s=%s\n", field, value);
588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_int(FILE *f, const char *field, int value, int def)
593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == def)
595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	fprintf(f, "\t%s=%d\n", field, value);
597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_bssid(FILE *f, struct wpa_ssid *ssid)
601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value = wpa_config_get(ssid, "bssid");
603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	fprintf(f, "\tbssid=%s\n", value);
606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_psk(FILE *f, struct wpa_ssid *ssid)
611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value = wpa_config_get(ssid, "psk");
613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	fprintf(f, "\tpsk=%s\n", value);
616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_proto(FILE *f, struct wpa_ssid *ssid)
621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->proto == DEFAULT_PROTO)
625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "proto");
628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "\tproto=%s\n", value);
632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_key_mgmt(FILE *f, struct wpa_ssid *ssid)
637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->key_mgmt == DEFAULT_KEY_MGMT)
641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "key_mgmt");
644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "\tkey_mgmt=%s\n", value);
648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_pairwise(FILE *f, struct wpa_ssid *ssid)
653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->pairwise_cipher == DEFAULT_PAIRWISE)
657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "pairwise");
660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "\tpairwise=%s\n", value);
664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_group(FILE *f, struct wpa_ssid *ssid)
669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->group_cipher == DEFAULT_GROUP)
673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "group");
676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "\tgroup=%s\n", value);
680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_auth_alg(FILE *f, struct wpa_ssid *ssid)
685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->auth_alg == 0)
689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "auth_alg");
692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "\tauth_alg=%s\n", value);
696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef IEEE8021X_EAPOL
701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_eap(FILE *f, struct wpa_ssid *ssid)
702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "eap");
706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "\teap=%s\n", value);
711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* IEEE8021X_EAPOL */
714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid)
717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char field[20], *value;
719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int res;
720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	res = os_snprintf(field, sizeof(field), "wep_key%d", idx);
722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res < 0 || (size_t) res >= sizeof(field))
723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, field);
725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value) {
726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "\t%s=%s\n", field, value);
727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(value);
728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int i;
735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define STR(t) write_str(f, #t, ssid)
737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define INT(t) write_int(f, #t, ssid->t, 0)
738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define INTe(t) write_int(f, #t, ssid->eap.t, 0)
739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define INT_DEF(t, def) write_int(f, #t, ssid->t, def)
740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define INT_DEFe(t, def) write_int(f, #t, ssid->eap.t, def)
741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ssid);
743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(scan_ssid);
744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_bssid(f, ssid);
745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_psk(f, ssid);
746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_proto(f, ssid);
747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_key_mgmt(f, ssid);
748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_pairwise(f, ssid);
749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_group(f, ssid);
750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_auth_alg(f, ssid);
751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef IEEE8021X_EAPOL
752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_eap(f, ssid);
753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(identity);
754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(anonymous_identity);
755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(password);
756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_cert);
757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_path);
758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(client_cert);
759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(private_key);
760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(private_key_passwd);
761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(dh_file);
762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(subject_match);
763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(altsubject_match);
764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_cert2);
765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_path2);
766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(client_cert2);
767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(private_key2);
768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(private_key2_passwd);
769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(dh_file2);
770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(subject_match2);
771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(altsubject_match2);
772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(phase1);
773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(phase2);
774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(pcsc);
775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(pin);
776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(engine_id);
777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(key_id);
778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(cert_id);
779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_cert_id);
780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(key2_id);
781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(pin2);
782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(engine2_id);
783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(cert2_id);
784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_cert2_id);
785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INTe(engine);
786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INTe(engine2);
787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* IEEE8021X_EAPOL */
789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < 4; i++)
790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		write_wep_key(f, i, ssid);
791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(wep_tx_keyidx);
792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(priority);
793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef IEEE8021X_EAPOL
794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND);
795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(pac_file);
796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE);
797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* IEEE8021X_EAPOL */
798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(mode);
799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(proactive_key_caching);
800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(disabled);
801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(peerkey);
802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W
803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(ieee80211w);
804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */
805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(id_str);
806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef STR
808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef INT
809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef INT_DEF
810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob)
815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	unsigned char *encoded;
817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	encoded = base64_encode(blob->data, blob->len, NULL);
819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (encoded == NULL)
820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
821526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
822526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded);
823526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(encoded);
824526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
825526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
826526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
827526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
828526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
829526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void wpa_config_write_global(FILE *f, struct wpa_config *config)
830526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
831526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE
832526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->ctrl_interface)
833526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface);
834526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->ctrl_interface_group)
835526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "ctrl_interface_group=%s\n",
836526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			config->ctrl_interface_group);
837526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
838526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->eapol_version != DEFAULT_EAPOL_VERSION)
839526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "eapol_version=%d\n", config->eapol_version);
840526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->ap_scan != DEFAULT_AP_SCAN)
841526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "ap_scan=%d\n", config->ap_scan);
842526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->fast_reauth != DEFAULT_FAST_REAUTH)
843526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "fast_reauth=%d\n", config->fast_reauth);
844526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef EAP_TLS_OPENSSL
845526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->opensc_engine_path)
846526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "opensc_engine_path=%s\n",
847526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			config->opensc_engine_path);
848526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->pkcs11_engine_path)
849526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "pkcs11_engine_path=%s\n",
850526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			config->pkcs11_engine_path);
851526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->pkcs11_module_path)
852526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "pkcs11_module_path=%s\n",
853526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			config->pkcs11_module_path);
854526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* EAP_TLS_OPENSSL */
855526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->driver_param)
856526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "driver_param=%s\n", config->driver_param);
857526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->dot11RSNAConfigPMKLifetime)
858526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "dot11RSNAConfigPMKLifetime=%d\n",
859526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			config->dot11RSNAConfigPMKLifetime);
860526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->dot11RSNAConfigPMKReauthThreshold)
861526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%d\n",
862526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			config->dot11RSNAConfigPMKReauthThreshold);
863526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->dot11RSNAConfigSATimeout)
864526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "dot11RSNAConfigSATimeout=%d\n",
865526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			config->dot11RSNAConfigSATimeout);
866526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->update_config)
867526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "update_config=%d\n", config->update_config);
868526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_WPS
869526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!is_nil_uuid(config->uuid)) {
870526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		char buf[40];
871526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		uuid_bin2str(config->uuid, buf, sizeof(buf));
872526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "uuid=%s\n", buf);
873526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
874526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->device_name)
875526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "device_name=%s\n", config->device_name);
876526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->manufacturer)
877526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "manufacturer=%s\n", config->manufacturer);
878526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->model_name)
879526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "model_name=%s\n", config->model_name);
880526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->model_number)
881526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "model_number=%s\n", config->model_number);
882526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->serial_number)
883526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "serial_number=%s\n", config->serial_number);
884526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->device_type)
885526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "device_type=%s\n", config->device_type);
886526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (WPA_GET_BE32(config->os_version))
887526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "os_version=%08x\n",
888526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			WPA_GET_BE32(config->os_version));
889526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->wps_cred_processing)
890526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "wps_cred_processing=%d\n",
891526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			config->wps_cred_processing);
892526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_WPS */
893526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config->country[0] && config->country[1]) {
894526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "country=%c%c\n",
895526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			config->country[0], config->country[1]);
896526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
897526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
898526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
899526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NO_CONFIG_WRITE */
900526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
901526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
902526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_config_write(const char *name, struct wpa_config *config)
903526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
904526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NO_CONFIG_WRITE
905526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	FILE *f;
906526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ssid *ssid;
907526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
908526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_config_blob *blob;
909526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
910526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ret = 0;
911526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
912526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name);
913526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
914526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	f = fopen(name, "w");
915526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (f == NULL) {
916526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name);
917526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
918526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
919526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
920526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_global(f, config);
921526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
922526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (ssid = config->ssid; ssid; ssid = ssid->next) {
923526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
924526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue; /* do not save temporary WPS networks */
925526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "\nnetwork={\n");
926526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_write_network(f, ssid);
927526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		fprintf(f, "}\n");
928526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
929526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
930526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NO_CONFIG_BLOBS
931526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (blob = config->blobs; blob; blob = blob->next) {
932526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ret = wpa_config_write_blob(f, blob);
933526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ret)
934526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
935526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
936526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NO_CONFIG_BLOBS */
937526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
938526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	fclose(f);
939526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
940526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully",
941526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   name, ret ? "un" : "");
942526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ret;
943526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* CONFIG_NO_CONFIG_WRITE */
944526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
945526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NO_CONFIG_WRITE */
946526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
947