16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer  * WPA Supplicant / Configuration backend: text file
33ff40c12SJohn Marino  * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer  *
53ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino  * See README for more details.
76d49e1aeSJan Lentfer  *
86d49e1aeSJan Lentfer  * This file implements a configuration backend for text files. All the
96d49e1aeSJan Lentfer  * configuration information is stored in a text file that uses a format
106d49e1aeSJan Lentfer  * described in the sample configuration file, wpa_supplicant.conf.
116d49e1aeSJan Lentfer  */
126d49e1aeSJan Lentfer 
136d49e1aeSJan Lentfer #include "includes.h"
14*a1157835SDaniel Fojt #ifdef ANDROID
15*a1157835SDaniel Fojt #include <sys/stat.h>
16*a1157835SDaniel Fojt #endif /* ANDROID */
176d49e1aeSJan Lentfer 
186d49e1aeSJan Lentfer #include "common.h"
196d49e1aeSJan Lentfer #include "config.h"
206d49e1aeSJan Lentfer #include "base64.h"
216d49e1aeSJan Lentfer #include "uuid.h"
22*a1157835SDaniel Fojt #include "common/ieee802_1x_defs.h"
233ff40c12SJohn Marino #include "p2p/p2p.h"
246d49e1aeSJan Lentfer #include "eap_peer/eap_methods.h"
253ff40c12SJohn Marino #include "eap_peer/eap.h"
263ff40c12SJohn Marino 
273ff40c12SJohn Marino 
newline_terminated(const char * buf,size_t buflen)283ff40c12SJohn Marino static int newline_terminated(const char *buf, size_t buflen)
293ff40c12SJohn Marino {
303ff40c12SJohn Marino 	size_t len = os_strlen(buf);
313ff40c12SJohn Marino 	if (len == 0)
323ff40c12SJohn Marino 		return 0;
333ff40c12SJohn Marino 	if (len == buflen - 1 && buf[buflen - 1] != '\r' &&
343ff40c12SJohn Marino 	    buf[len - 1] != '\n')
353ff40c12SJohn Marino 		return 0;
363ff40c12SJohn Marino 	return 1;
373ff40c12SJohn Marino }
383ff40c12SJohn Marino 
393ff40c12SJohn Marino 
skip_line_end(FILE * stream)403ff40c12SJohn Marino static void skip_line_end(FILE *stream)
413ff40c12SJohn Marino {
423ff40c12SJohn Marino 	char buf[100];
433ff40c12SJohn Marino 	while (fgets(buf, sizeof(buf), stream)) {
443ff40c12SJohn Marino 		buf[sizeof(buf) - 1] = '\0';
453ff40c12SJohn Marino 		if (newline_terminated(buf, sizeof(buf)))
463ff40c12SJohn Marino 			return;
473ff40c12SJohn Marino 	}
483ff40c12SJohn Marino }
496d49e1aeSJan Lentfer 
506d49e1aeSJan Lentfer 
516d49e1aeSJan Lentfer /**
526d49e1aeSJan Lentfer  * wpa_config_get_line - Read the next configuration file line
536d49e1aeSJan Lentfer  * @s: Buffer for the line
546d49e1aeSJan Lentfer  * @size: The buffer length
556d49e1aeSJan Lentfer  * @stream: File stream to read from
566d49e1aeSJan Lentfer  * @line: Pointer to a variable storing the file line number
576d49e1aeSJan Lentfer  * @_pos: Buffer for the pointer to the beginning of data on the text line or
586d49e1aeSJan Lentfer  * %NULL if not needed (returned value used instead)
596d49e1aeSJan Lentfer  * Returns: Pointer to the beginning of data on the text line or %NULL if no
606d49e1aeSJan Lentfer  * more text lines are available.
616d49e1aeSJan Lentfer  *
626d49e1aeSJan Lentfer  * This function reads the next non-empty line from the configuration file and
636d49e1aeSJan Lentfer  * removes comments. The returned string is guaranteed to be null-terminated.
646d49e1aeSJan Lentfer  */
wpa_config_get_line(char * s,int size,FILE * stream,int * line,char ** _pos)656d49e1aeSJan Lentfer static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line,
666d49e1aeSJan Lentfer 				  char **_pos)
676d49e1aeSJan Lentfer {
686d49e1aeSJan Lentfer 	char *pos, *end, *sstart;
696d49e1aeSJan Lentfer 
706d49e1aeSJan Lentfer 	while (fgets(s, size, stream)) {
716d49e1aeSJan Lentfer 		(*line)++;
726d49e1aeSJan Lentfer 		s[size - 1] = '\0';
733ff40c12SJohn Marino 		if (!newline_terminated(s, size)) {
743ff40c12SJohn Marino 			/*
753ff40c12SJohn Marino 			 * The line was truncated - skip rest of it to avoid
763ff40c12SJohn Marino 			 * confusing error messages.
773ff40c12SJohn Marino 			 */
783ff40c12SJohn Marino 			wpa_printf(MSG_INFO, "Long line in configuration file "
793ff40c12SJohn Marino 				   "truncated");
803ff40c12SJohn Marino 			skip_line_end(stream);
813ff40c12SJohn Marino 		}
826d49e1aeSJan Lentfer 		pos = s;
836d49e1aeSJan Lentfer 
846d49e1aeSJan Lentfer 		/* Skip white space from the beginning of line. */
856d49e1aeSJan Lentfer 		while (*pos == ' ' || *pos == '\t' || *pos == '\r')
866d49e1aeSJan Lentfer 			pos++;
876d49e1aeSJan Lentfer 
886d49e1aeSJan Lentfer 		/* Skip comment lines and empty lines */
896d49e1aeSJan Lentfer 		if (*pos == '#' || *pos == '\n' || *pos == '\0')
906d49e1aeSJan Lentfer 			continue;
916d49e1aeSJan Lentfer 
926d49e1aeSJan Lentfer 		/*
936d49e1aeSJan Lentfer 		 * Remove # comments unless they are within a double quoted
946d49e1aeSJan Lentfer 		 * string.
956d49e1aeSJan Lentfer 		 */
966d49e1aeSJan Lentfer 		sstart = os_strchr(pos, '"');
976d49e1aeSJan Lentfer 		if (sstart)
986d49e1aeSJan Lentfer 			sstart = os_strrchr(sstart + 1, '"');
996d49e1aeSJan Lentfer 		if (!sstart)
1006d49e1aeSJan Lentfer 			sstart = pos;
1016d49e1aeSJan Lentfer 		end = os_strchr(sstart, '#');
1026d49e1aeSJan Lentfer 		if (end)
1036d49e1aeSJan Lentfer 			*end-- = '\0';
1046d49e1aeSJan Lentfer 		else
1056d49e1aeSJan Lentfer 			end = pos + os_strlen(pos) - 1;
1066d49e1aeSJan Lentfer 
1076d49e1aeSJan Lentfer 		/* Remove trailing white space. */
1086d49e1aeSJan Lentfer 		while (end > pos &&
1096d49e1aeSJan Lentfer 		       (*end == '\n' || *end == ' ' || *end == '\t' ||
1106d49e1aeSJan Lentfer 			*end == '\r'))
1116d49e1aeSJan Lentfer 			*end-- = '\0';
1126d49e1aeSJan Lentfer 
1136d49e1aeSJan Lentfer 		if (*pos == '\0')
1146d49e1aeSJan Lentfer 			continue;
1156d49e1aeSJan Lentfer 
1166d49e1aeSJan Lentfer 		if (_pos)
1176d49e1aeSJan Lentfer 			*_pos = pos;
1186d49e1aeSJan Lentfer 		return pos;
1196d49e1aeSJan Lentfer 	}
1206d49e1aeSJan Lentfer 
1216d49e1aeSJan Lentfer 	if (_pos)
1226d49e1aeSJan Lentfer 		*_pos = NULL;
1236d49e1aeSJan Lentfer 	return NULL;
1246d49e1aeSJan Lentfer }
1256d49e1aeSJan Lentfer 
1266d49e1aeSJan Lentfer 
wpa_config_validate_network(struct wpa_ssid * ssid,int line)1276d49e1aeSJan Lentfer static int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
1286d49e1aeSJan Lentfer {
1296d49e1aeSJan Lentfer 	int errors = 0;
1306d49e1aeSJan Lentfer 
1316d49e1aeSJan Lentfer 	if (ssid->passphrase) {
1326d49e1aeSJan Lentfer 		if (ssid->psk_set) {
1336d49e1aeSJan Lentfer 			wpa_printf(MSG_ERROR, "Line %d: both PSK and "
1346d49e1aeSJan Lentfer 				   "passphrase configured.", line);
1356d49e1aeSJan Lentfer 			errors++;
1366d49e1aeSJan Lentfer 		}
1376d49e1aeSJan Lentfer 		wpa_config_update_psk(ssid);
1386d49e1aeSJan Lentfer 	}
1396d49e1aeSJan Lentfer 
140*a1157835SDaniel Fojt 	if (ssid->disabled == 2)
141*a1157835SDaniel Fojt 		ssid->p2p_persistent_group = 1;
142*a1157835SDaniel Fojt 
1436d49e1aeSJan Lentfer 	if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
144*a1157835SDaniel Fojt 	    !(ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 |
145*a1157835SDaniel Fojt 				       WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256 |
146*a1157835SDaniel Fojt 				       WPA_CIPHER_NONE))) {
1476d49e1aeSJan Lentfer 		/* Group cipher cannot be stronger than the pairwise cipher. */
1486d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher"
1496d49e1aeSJan Lentfer 			   " list since it was not allowed for pairwise "
1506d49e1aeSJan Lentfer 			   "cipher", line);
1516d49e1aeSJan Lentfer 		ssid->group_cipher &= ~WPA_CIPHER_CCMP;
1526d49e1aeSJan Lentfer 	}
1536d49e1aeSJan Lentfer 
154*a1157835SDaniel Fojt 	if (ssid->mode == WPAS_MODE_MESH &&
155*a1157835SDaniel Fojt 	    (ssid->key_mgmt != WPA_KEY_MGMT_NONE &&
156*a1157835SDaniel Fojt 	    ssid->key_mgmt != WPA_KEY_MGMT_SAE)) {
157*a1157835SDaniel Fojt 		wpa_printf(MSG_ERROR,
158*a1157835SDaniel Fojt 			   "Line %d: key_mgmt for mesh network should be open or SAE",
159*a1157835SDaniel Fojt 			   line);
160*a1157835SDaniel Fojt 		errors++;
161*a1157835SDaniel Fojt 	}
162*a1157835SDaniel Fojt 
163*a1157835SDaniel Fojt #ifdef CONFIG_OCV
164*a1157835SDaniel Fojt 	if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
165*a1157835SDaniel Fojt 		wpa_printf(MSG_ERROR,
166*a1157835SDaniel Fojt 			   "Line %d: PMF needs to be enabled whenever using OCV",
167*a1157835SDaniel Fojt 			   line);
168*a1157835SDaniel Fojt 		errors++;
169*a1157835SDaniel Fojt 	}
170*a1157835SDaniel Fojt #endif /* CONFIG_OCV */
171*a1157835SDaniel Fojt 
1726d49e1aeSJan Lentfer 	return errors;
1736d49e1aeSJan Lentfer }
1746d49e1aeSJan Lentfer 
1756d49e1aeSJan Lentfer 
wpa_config_read_network(FILE * f,int * line,int id)1766d49e1aeSJan Lentfer static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id)
1776d49e1aeSJan Lentfer {
1786d49e1aeSJan Lentfer 	struct wpa_ssid *ssid;
1796d49e1aeSJan Lentfer 	int errors = 0, end = 0;
1803ff40c12SJohn Marino 	char buf[2000], *pos, *pos2;
1816d49e1aeSJan Lentfer 
1826d49e1aeSJan Lentfer 	wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block",
1836d49e1aeSJan Lentfer 		   *line);
1846d49e1aeSJan Lentfer 	ssid = os_zalloc(sizeof(*ssid));
1856d49e1aeSJan Lentfer 	if (ssid == NULL)
1866d49e1aeSJan Lentfer 		return NULL;
1873ff40c12SJohn Marino 	dl_list_init(&ssid->psk_list);
1886d49e1aeSJan Lentfer 	ssid->id = id;
1896d49e1aeSJan Lentfer 
1906d49e1aeSJan Lentfer 	wpa_config_set_network_defaults(ssid);
1916d49e1aeSJan Lentfer 
1926d49e1aeSJan Lentfer 	while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
1936d49e1aeSJan Lentfer 		if (os_strcmp(pos, "}") == 0) {
1946d49e1aeSJan Lentfer 			end = 1;
1956d49e1aeSJan Lentfer 			break;
1966d49e1aeSJan Lentfer 		}
1976d49e1aeSJan Lentfer 
1986d49e1aeSJan Lentfer 		pos2 = os_strchr(pos, '=');
1996d49e1aeSJan Lentfer 		if (pos2 == NULL) {
2006d49e1aeSJan Lentfer 			wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line "
2016d49e1aeSJan Lentfer 				   "'%s'.", *line, pos);
2026d49e1aeSJan Lentfer 			errors++;
2036d49e1aeSJan Lentfer 			continue;
2046d49e1aeSJan Lentfer 		}
2056d49e1aeSJan Lentfer 
2066d49e1aeSJan Lentfer 		*pos2++ = '\0';
2076d49e1aeSJan Lentfer 		if (*pos2 == '"') {
2086d49e1aeSJan Lentfer 			if (os_strchr(pos2 + 1, '"') == NULL) {
2096d49e1aeSJan Lentfer 				wpa_printf(MSG_ERROR, "Line %d: invalid "
2106d49e1aeSJan Lentfer 					   "quotation '%s'.", *line, pos2);
2116d49e1aeSJan Lentfer 				errors++;
2126d49e1aeSJan Lentfer 				continue;
2136d49e1aeSJan Lentfer 			}
2146d49e1aeSJan Lentfer 		}
2156d49e1aeSJan Lentfer 
2166d49e1aeSJan Lentfer 		if (wpa_config_set(ssid, pos, pos2, *line) < 0)
2176d49e1aeSJan Lentfer 			errors++;
2186d49e1aeSJan Lentfer 	}
2196d49e1aeSJan Lentfer 
2206d49e1aeSJan Lentfer 	if (!end) {
2216d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "Line %d: network block was not "
2226d49e1aeSJan Lentfer 			   "terminated properly.", *line);
2236d49e1aeSJan Lentfer 		errors++;
2246d49e1aeSJan Lentfer 	}
2256d49e1aeSJan Lentfer 
2266d49e1aeSJan Lentfer 	errors += wpa_config_validate_network(ssid, *line);
2276d49e1aeSJan Lentfer 
2286d49e1aeSJan Lentfer 	if (errors) {
2296d49e1aeSJan Lentfer 		wpa_config_free_ssid(ssid);
2306d49e1aeSJan Lentfer 		ssid = NULL;
2316d49e1aeSJan Lentfer 	}
2326d49e1aeSJan Lentfer 
2336d49e1aeSJan Lentfer 	return ssid;
2346d49e1aeSJan Lentfer }
2356d49e1aeSJan Lentfer 
2366d49e1aeSJan Lentfer 
wpa_config_read_cred(FILE * f,int * line,int id)2373ff40c12SJohn Marino static struct wpa_cred * wpa_config_read_cred(FILE *f, int *line, int id)
2383ff40c12SJohn Marino {
2393ff40c12SJohn Marino 	struct wpa_cred *cred;
2403ff40c12SJohn Marino 	int errors = 0, end = 0;
2413ff40c12SJohn Marino 	char buf[256], *pos, *pos2;
2423ff40c12SJohn Marino 
2433ff40c12SJohn Marino 	wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new cred block", *line);
2443ff40c12SJohn Marino 	cred = os_zalloc(sizeof(*cred));
2453ff40c12SJohn Marino 	if (cred == NULL)
2463ff40c12SJohn Marino 		return NULL;
2473ff40c12SJohn Marino 	cred->id = id;
248*a1157835SDaniel Fojt 	cred->sim_num = DEFAULT_USER_SELECTED_SIM;
2493ff40c12SJohn Marino 
2503ff40c12SJohn Marino 	while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
2513ff40c12SJohn Marino 		if (os_strcmp(pos, "}") == 0) {
2523ff40c12SJohn Marino 			end = 1;
2533ff40c12SJohn Marino 			break;
2543ff40c12SJohn Marino 		}
2553ff40c12SJohn Marino 
2563ff40c12SJohn Marino 		pos2 = os_strchr(pos, '=');
2573ff40c12SJohn Marino 		if (pos2 == NULL) {
2583ff40c12SJohn Marino 			wpa_printf(MSG_ERROR, "Line %d: Invalid cred line "
2593ff40c12SJohn Marino 				   "'%s'.", *line, pos);
2603ff40c12SJohn Marino 			errors++;
2613ff40c12SJohn Marino 			continue;
2623ff40c12SJohn Marino 		}
2633ff40c12SJohn Marino 
2643ff40c12SJohn Marino 		*pos2++ = '\0';
2653ff40c12SJohn Marino 		if (*pos2 == '"') {
2663ff40c12SJohn Marino 			if (os_strchr(pos2 + 1, '"') == NULL) {
2673ff40c12SJohn Marino 				wpa_printf(MSG_ERROR, "Line %d: invalid "
2683ff40c12SJohn Marino 					   "quotation '%s'.", *line, pos2);
2693ff40c12SJohn Marino 				errors++;
2703ff40c12SJohn Marino 				continue;
2713ff40c12SJohn Marino 			}
2723ff40c12SJohn Marino 		}
2733ff40c12SJohn Marino 
2743ff40c12SJohn Marino 		if (wpa_config_set_cred(cred, pos, pos2, *line) < 0)
2753ff40c12SJohn Marino 			errors++;
2763ff40c12SJohn Marino 	}
2773ff40c12SJohn Marino 
2783ff40c12SJohn Marino 	if (!end) {
2793ff40c12SJohn Marino 		wpa_printf(MSG_ERROR, "Line %d: cred block was not "
2803ff40c12SJohn Marino 			   "terminated properly.", *line);
2813ff40c12SJohn Marino 		errors++;
2823ff40c12SJohn Marino 	}
2833ff40c12SJohn Marino 
2843ff40c12SJohn Marino 	if (errors) {
2853ff40c12SJohn Marino 		wpa_config_free_cred(cred);
2863ff40c12SJohn Marino 		cred = NULL;
2873ff40c12SJohn Marino 	}
2883ff40c12SJohn Marino 
2893ff40c12SJohn Marino 	return cred;
2903ff40c12SJohn Marino }
2913ff40c12SJohn Marino 
2923ff40c12SJohn Marino 
2936d49e1aeSJan Lentfer #ifndef CONFIG_NO_CONFIG_BLOBS
wpa_config_read_blob(FILE * f,int * line,const char * name)2946d49e1aeSJan Lentfer static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line,
2956d49e1aeSJan Lentfer 						     const char *name)
2966d49e1aeSJan Lentfer {
2976d49e1aeSJan Lentfer 	struct wpa_config_blob *blob;
2986d49e1aeSJan Lentfer 	char buf[256], *pos;
2996d49e1aeSJan Lentfer 	unsigned char *encoded = NULL, *nencoded;
3006d49e1aeSJan Lentfer 	int end = 0;
3016d49e1aeSJan Lentfer 	size_t encoded_len = 0, len;
3026d49e1aeSJan Lentfer 
3036d49e1aeSJan Lentfer 	wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new named blob '%s'",
3046d49e1aeSJan Lentfer 		   *line, name);
3056d49e1aeSJan Lentfer 
3066d49e1aeSJan Lentfer 	while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
3076d49e1aeSJan Lentfer 		if (os_strcmp(pos, "}") == 0) {
3086d49e1aeSJan Lentfer 			end = 1;
3096d49e1aeSJan Lentfer 			break;
3106d49e1aeSJan Lentfer 		}
3116d49e1aeSJan Lentfer 
3126d49e1aeSJan Lentfer 		len = os_strlen(pos);
3136d49e1aeSJan Lentfer 		nencoded = os_realloc(encoded, encoded_len + len);
3146d49e1aeSJan Lentfer 		if (nencoded == NULL) {
3156d49e1aeSJan Lentfer 			wpa_printf(MSG_ERROR, "Line %d: not enough memory for "
3166d49e1aeSJan Lentfer 				   "blob", *line);
3176d49e1aeSJan Lentfer 			os_free(encoded);
3186d49e1aeSJan Lentfer 			return NULL;
3196d49e1aeSJan Lentfer 		}
3206d49e1aeSJan Lentfer 		encoded = nencoded;
3216d49e1aeSJan Lentfer 		os_memcpy(encoded + encoded_len, pos, len);
3226d49e1aeSJan Lentfer 		encoded_len += len;
3236d49e1aeSJan Lentfer 	}
3246d49e1aeSJan Lentfer 
325*a1157835SDaniel Fojt 	if (!end || !encoded) {
3266d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "Line %d: blob was not terminated "
3276d49e1aeSJan Lentfer 			   "properly", *line);
3286d49e1aeSJan Lentfer 		os_free(encoded);
3296d49e1aeSJan Lentfer 		return NULL;
3306d49e1aeSJan Lentfer 	}
3316d49e1aeSJan Lentfer 
3326d49e1aeSJan Lentfer 	blob = os_zalloc(sizeof(*blob));
3336d49e1aeSJan Lentfer 	if (blob == NULL) {
3346d49e1aeSJan Lentfer 		os_free(encoded);
3356d49e1aeSJan Lentfer 		return NULL;
3366d49e1aeSJan Lentfer 	}
3376d49e1aeSJan Lentfer 	blob->name = os_strdup(name);
3386d49e1aeSJan Lentfer 	blob->data = base64_decode(encoded, encoded_len, &blob->len);
3396d49e1aeSJan Lentfer 	os_free(encoded);
3406d49e1aeSJan Lentfer 
3416d49e1aeSJan Lentfer 	if (blob->name == NULL || blob->data == NULL) {
3426d49e1aeSJan Lentfer 		wpa_config_free_blob(blob);
3436d49e1aeSJan Lentfer 		return NULL;
3446d49e1aeSJan Lentfer 	}
3456d49e1aeSJan Lentfer 
3466d49e1aeSJan Lentfer 	return blob;
3476d49e1aeSJan Lentfer }
3486d49e1aeSJan Lentfer 
3496d49e1aeSJan Lentfer 
wpa_config_process_blob(struct wpa_config * config,FILE * f,int * line,char * bname)3506d49e1aeSJan Lentfer static int wpa_config_process_blob(struct wpa_config *config, FILE *f,
3516d49e1aeSJan Lentfer 				   int *line, char *bname)
3526d49e1aeSJan Lentfer {
3536d49e1aeSJan Lentfer 	char *name_end;
3546d49e1aeSJan Lentfer 	struct wpa_config_blob *blob;
3556d49e1aeSJan Lentfer 
3566d49e1aeSJan Lentfer 	name_end = os_strchr(bname, '=');
3576d49e1aeSJan Lentfer 	if (name_end == NULL) {
3586d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "Line %d: no blob name terminator",
3596d49e1aeSJan Lentfer 			   *line);
3606d49e1aeSJan Lentfer 		return -1;
3616d49e1aeSJan Lentfer 	}
3626d49e1aeSJan Lentfer 	*name_end = '\0';
3636d49e1aeSJan Lentfer 
3646d49e1aeSJan Lentfer 	blob = wpa_config_read_blob(f, line, bname);
3656d49e1aeSJan Lentfer 	if (blob == NULL) {
3666d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "Line %d: failed to read blob %s",
3676d49e1aeSJan Lentfer 			   *line, bname);
3686d49e1aeSJan Lentfer 		return -1;
3696d49e1aeSJan Lentfer 	}
3706d49e1aeSJan Lentfer 	wpa_config_set_blob(config, blob);
3716d49e1aeSJan Lentfer 	return 0;
3726d49e1aeSJan Lentfer }
3736d49e1aeSJan Lentfer #endif /* CONFIG_NO_CONFIG_BLOBS */
3746d49e1aeSJan Lentfer 
3756d49e1aeSJan Lentfer 
wpa_config_read(const char * name,struct wpa_config * cfgp)3763ff40c12SJohn Marino struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
3776d49e1aeSJan Lentfer {
3786d49e1aeSJan Lentfer 	FILE *f;
3793ff40c12SJohn Marino 	char buf[512], *pos;
3806d49e1aeSJan Lentfer 	int errors = 0, line = 0;
381*a1157835SDaniel Fojt 	struct wpa_ssid *ssid, *tail, *head;
382*a1157835SDaniel Fojt 	struct wpa_cred *cred, *cred_tail, *cred_head;
3836d49e1aeSJan Lentfer 	struct wpa_config *config;
3846d49e1aeSJan Lentfer 	int id = 0;
3853ff40c12SJohn Marino 	int cred_id = 0;
3866d49e1aeSJan Lentfer 
3873ff40c12SJohn Marino 	if (name == NULL)
3886d49e1aeSJan Lentfer 		return NULL;
3893ff40c12SJohn Marino 	if (cfgp)
3903ff40c12SJohn Marino 		config = cfgp;
3913ff40c12SJohn Marino 	else
3923ff40c12SJohn Marino 		config = wpa_config_alloc_empty(NULL, NULL);
3933ff40c12SJohn Marino 	if (config == NULL) {
3943ff40c12SJohn Marino 		wpa_printf(MSG_ERROR, "Failed to allocate config file "
3953ff40c12SJohn Marino 			   "structure");
3963ff40c12SJohn Marino 		return NULL;
3973ff40c12SJohn Marino 	}
398*a1157835SDaniel Fojt 	tail = head = config->ssid;
399*a1157835SDaniel Fojt 	while (tail && tail->next)
400*a1157835SDaniel Fojt 		tail = tail->next;
401*a1157835SDaniel Fojt 	cred_tail = cred_head = config->cred;
402*a1157835SDaniel Fojt 	while (cred_tail && cred_tail->next)
403*a1157835SDaniel Fojt 		cred_tail = cred_tail->next;
4043ff40c12SJohn Marino 
4056d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
4066d49e1aeSJan Lentfer 	f = fopen(name, "r");
4076d49e1aeSJan Lentfer 	if (f == NULL) {
4083ff40c12SJohn Marino 		wpa_printf(MSG_ERROR, "Failed to open config file '%s', "
4093ff40c12SJohn Marino 			   "error: %s", name, strerror(errno));
410*a1157835SDaniel Fojt 		if (config != cfgp)
4116d49e1aeSJan Lentfer 			os_free(config);
4126d49e1aeSJan Lentfer 		return NULL;
4136d49e1aeSJan Lentfer 	}
4146d49e1aeSJan Lentfer 
4156d49e1aeSJan Lentfer 	while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {
4166d49e1aeSJan Lentfer 		if (os_strcmp(pos, "network={") == 0) {
4176d49e1aeSJan Lentfer 			ssid = wpa_config_read_network(f, &line, id++);
4186d49e1aeSJan Lentfer 			if (ssid == NULL) {
4196d49e1aeSJan Lentfer 				wpa_printf(MSG_ERROR, "Line %d: failed to "
4206d49e1aeSJan Lentfer 					   "parse network block.", line);
4216d49e1aeSJan Lentfer 				errors++;
4226d49e1aeSJan Lentfer 				continue;
4236d49e1aeSJan Lentfer 			}
4246d49e1aeSJan Lentfer 			if (head == NULL) {
4256d49e1aeSJan Lentfer 				head = tail = ssid;
4266d49e1aeSJan Lentfer 			} else {
4276d49e1aeSJan Lentfer 				tail->next = ssid;
4286d49e1aeSJan Lentfer 				tail = ssid;
4296d49e1aeSJan Lentfer 			}
4306d49e1aeSJan Lentfer 			if (wpa_config_add_prio_network(config, ssid)) {
4316d49e1aeSJan Lentfer 				wpa_printf(MSG_ERROR, "Line %d: failed to add "
4326d49e1aeSJan Lentfer 					   "network block to priority list.",
4336d49e1aeSJan Lentfer 					   line);
4346d49e1aeSJan Lentfer 				errors++;
4356d49e1aeSJan Lentfer 				continue;
4366d49e1aeSJan Lentfer 			}
4373ff40c12SJohn Marino 		} else if (os_strcmp(pos, "cred={") == 0) {
4383ff40c12SJohn Marino 			cred = wpa_config_read_cred(f, &line, cred_id++);
4393ff40c12SJohn Marino 			if (cred == NULL) {
4403ff40c12SJohn Marino 				wpa_printf(MSG_ERROR, "Line %d: failed to "
4413ff40c12SJohn Marino 					   "parse cred block.", line);
4423ff40c12SJohn Marino 				errors++;
4433ff40c12SJohn Marino 				continue;
4443ff40c12SJohn Marino 			}
4453ff40c12SJohn Marino 			if (cred_head == NULL) {
4463ff40c12SJohn Marino 				cred_head = cred_tail = cred;
4473ff40c12SJohn Marino 			} else {
4483ff40c12SJohn Marino 				cred_tail->next = cred;
4493ff40c12SJohn Marino 				cred_tail = cred;
4503ff40c12SJohn Marino 			}
4516d49e1aeSJan Lentfer #ifndef CONFIG_NO_CONFIG_BLOBS
4526d49e1aeSJan Lentfer 		} else if (os_strncmp(pos, "blob-base64-", 12) == 0) {
4536d49e1aeSJan Lentfer 			if (wpa_config_process_blob(config, f, &line, pos + 12)
4546d49e1aeSJan Lentfer 			    < 0) {
4553ff40c12SJohn Marino 				wpa_printf(MSG_ERROR, "Line %d: failed to "
4563ff40c12SJohn Marino 					   "process blob.", line);
4576d49e1aeSJan Lentfer 				errors++;
4586d49e1aeSJan Lentfer 				continue;
4596d49e1aeSJan Lentfer 			}
4606d49e1aeSJan Lentfer #endif /* CONFIG_NO_CONFIG_BLOBS */
4616d49e1aeSJan Lentfer 		} else if (wpa_config_process_global(config, pos, line) < 0) {
4626d49e1aeSJan Lentfer 			wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "
4636d49e1aeSJan Lentfer 				   "line '%s'.", line, pos);
4646d49e1aeSJan Lentfer 			errors++;
4656d49e1aeSJan Lentfer 			continue;
4666d49e1aeSJan Lentfer 		}
4676d49e1aeSJan Lentfer 	}
4686d49e1aeSJan Lentfer 
4696d49e1aeSJan Lentfer 	fclose(f);
4706d49e1aeSJan Lentfer 
4716d49e1aeSJan Lentfer 	config->ssid = head;
4726d49e1aeSJan Lentfer 	wpa_config_debug_dump_networks(config);
4733ff40c12SJohn Marino 	config->cred = cred_head;
4746d49e1aeSJan Lentfer 
4753ff40c12SJohn Marino #ifndef WPA_IGNORE_CONFIG_ERRORS
4766d49e1aeSJan Lentfer 	if (errors) {
477*a1157835SDaniel Fojt 		if (config != cfgp)
4786d49e1aeSJan Lentfer 			wpa_config_free(config);
4796d49e1aeSJan Lentfer 		config = NULL;
4806d49e1aeSJan Lentfer 		head = NULL;
4816d49e1aeSJan Lentfer 	}
4823ff40c12SJohn Marino #endif /* WPA_IGNORE_CONFIG_ERRORS */
4836d49e1aeSJan Lentfer 
4846d49e1aeSJan Lentfer 	return config;
4856d49e1aeSJan Lentfer }
4866d49e1aeSJan Lentfer 
4876d49e1aeSJan Lentfer 
4886d49e1aeSJan Lentfer #ifndef CONFIG_NO_CONFIG_WRITE
4896d49e1aeSJan Lentfer 
write_str(FILE * f,const char * field,struct wpa_ssid * ssid)4906d49e1aeSJan Lentfer static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid)
4916d49e1aeSJan Lentfer {
4926d49e1aeSJan Lentfer 	char *value = wpa_config_get(ssid, field);
4936d49e1aeSJan Lentfer 	if (value == NULL)
4946d49e1aeSJan Lentfer 		return;
4956d49e1aeSJan Lentfer 	fprintf(f, "\t%s=%s\n", field, value);
496*a1157835SDaniel Fojt 	str_clear_free(value);
4976d49e1aeSJan Lentfer }
4986d49e1aeSJan Lentfer 
4996d49e1aeSJan Lentfer 
write_int(FILE * f,const char * field,int value,int def)5006d49e1aeSJan Lentfer static void write_int(FILE *f, const char *field, int value, int def)
5016d49e1aeSJan Lentfer {
5026d49e1aeSJan Lentfer 	if (value == def)
5036d49e1aeSJan Lentfer 		return;
5046d49e1aeSJan Lentfer 	fprintf(f, "\t%s=%d\n", field, value);
5056d49e1aeSJan Lentfer }
5066d49e1aeSJan Lentfer 
5076d49e1aeSJan Lentfer 
write_bssid(FILE * f,struct wpa_ssid * ssid)5086d49e1aeSJan Lentfer static void write_bssid(FILE *f, struct wpa_ssid *ssid)
5096d49e1aeSJan Lentfer {
5106d49e1aeSJan Lentfer 	char *value = wpa_config_get(ssid, "bssid");
5116d49e1aeSJan Lentfer 	if (value == NULL)
5126d49e1aeSJan Lentfer 		return;
5136d49e1aeSJan Lentfer 	fprintf(f, "\tbssid=%s\n", value);
5146d49e1aeSJan Lentfer 	os_free(value);
5156d49e1aeSJan Lentfer }
5166d49e1aeSJan Lentfer 
5176d49e1aeSJan Lentfer 
write_bssid_hint(FILE * f,struct wpa_ssid * ssid)518*a1157835SDaniel Fojt static void write_bssid_hint(FILE *f, struct wpa_ssid *ssid)
519*a1157835SDaniel Fojt {
520*a1157835SDaniel Fojt 	char *value = wpa_config_get(ssid, "bssid_hint");
521*a1157835SDaniel Fojt 
522*a1157835SDaniel Fojt 	if (!value)
523*a1157835SDaniel Fojt 		return;
524*a1157835SDaniel Fojt 	fprintf(f, "\tbssid_hint=%s\n", value);
525*a1157835SDaniel Fojt 	os_free(value);
526*a1157835SDaniel Fojt }
527*a1157835SDaniel Fojt 
528*a1157835SDaniel Fojt 
write_psk(FILE * f,struct wpa_ssid * ssid)5296d49e1aeSJan Lentfer static void write_psk(FILE *f, struct wpa_ssid *ssid)
5306d49e1aeSJan Lentfer {
531*a1157835SDaniel Fojt 	char *value;
532*a1157835SDaniel Fojt 
533*a1157835SDaniel Fojt 	if (ssid->mem_only_psk)
534*a1157835SDaniel Fojt 		return;
535*a1157835SDaniel Fojt 
536*a1157835SDaniel Fojt 	value = wpa_config_get(ssid, "psk");
5376d49e1aeSJan Lentfer 	if (value == NULL)
5386d49e1aeSJan Lentfer 		return;
5396d49e1aeSJan Lentfer 	fprintf(f, "\tpsk=%s\n", value);
5406d49e1aeSJan Lentfer 	os_free(value);
5416d49e1aeSJan Lentfer }
5426d49e1aeSJan Lentfer 
5436d49e1aeSJan Lentfer 
write_proto(FILE * f,struct wpa_ssid * ssid)5446d49e1aeSJan Lentfer static void write_proto(FILE *f, struct wpa_ssid *ssid)
5456d49e1aeSJan Lentfer {
5466d49e1aeSJan Lentfer 	char *value;
5476d49e1aeSJan Lentfer 
5486d49e1aeSJan Lentfer 	if (ssid->proto == DEFAULT_PROTO)
5496d49e1aeSJan Lentfer 		return;
5506d49e1aeSJan Lentfer 
5516d49e1aeSJan Lentfer 	value = wpa_config_get(ssid, "proto");
5526d49e1aeSJan Lentfer 	if (value == NULL)
5536d49e1aeSJan Lentfer 		return;
5546d49e1aeSJan Lentfer 	if (value[0])
5556d49e1aeSJan Lentfer 		fprintf(f, "\tproto=%s\n", value);
5566d49e1aeSJan Lentfer 	os_free(value);
5576d49e1aeSJan Lentfer }
5586d49e1aeSJan Lentfer 
5596d49e1aeSJan Lentfer 
write_key_mgmt(FILE * f,struct wpa_ssid * ssid)5606d49e1aeSJan Lentfer static void write_key_mgmt(FILE *f, struct wpa_ssid *ssid)
5616d49e1aeSJan Lentfer {
5626d49e1aeSJan Lentfer 	char *value;
5636d49e1aeSJan Lentfer 
5646d49e1aeSJan Lentfer 	if (ssid->key_mgmt == DEFAULT_KEY_MGMT)
5656d49e1aeSJan Lentfer 		return;
5666d49e1aeSJan Lentfer 
5676d49e1aeSJan Lentfer 	value = wpa_config_get(ssid, "key_mgmt");
5686d49e1aeSJan Lentfer 	if (value == NULL)
5696d49e1aeSJan Lentfer 		return;
5706d49e1aeSJan Lentfer 	if (value[0])
5716d49e1aeSJan Lentfer 		fprintf(f, "\tkey_mgmt=%s\n", value);
5726d49e1aeSJan Lentfer 	os_free(value);
5736d49e1aeSJan Lentfer }
5746d49e1aeSJan Lentfer 
5756d49e1aeSJan Lentfer 
write_pairwise(FILE * f,struct wpa_ssid * ssid)5766d49e1aeSJan Lentfer static void write_pairwise(FILE *f, struct wpa_ssid *ssid)
5776d49e1aeSJan Lentfer {
5786d49e1aeSJan Lentfer 	char *value;
5796d49e1aeSJan Lentfer 
5806d49e1aeSJan Lentfer 	if (ssid->pairwise_cipher == DEFAULT_PAIRWISE)
5816d49e1aeSJan Lentfer 		return;
5826d49e1aeSJan Lentfer 
5836d49e1aeSJan Lentfer 	value = wpa_config_get(ssid, "pairwise");
5846d49e1aeSJan Lentfer 	if (value == NULL)
5856d49e1aeSJan Lentfer 		return;
5866d49e1aeSJan Lentfer 	if (value[0])
5876d49e1aeSJan Lentfer 		fprintf(f, "\tpairwise=%s\n", value);
5886d49e1aeSJan Lentfer 	os_free(value);
5896d49e1aeSJan Lentfer }
5906d49e1aeSJan Lentfer 
5916d49e1aeSJan Lentfer 
write_group(FILE * f,struct wpa_ssid * ssid)5926d49e1aeSJan Lentfer static void write_group(FILE *f, struct wpa_ssid *ssid)
5936d49e1aeSJan Lentfer {
5946d49e1aeSJan Lentfer 	char *value;
5956d49e1aeSJan Lentfer 
5966d49e1aeSJan Lentfer 	if (ssid->group_cipher == DEFAULT_GROUP)
5976d49e1aeSJan Lentfer 		return;
5986d49e1aeSJan Lentfer 
5996d49e1aeSJan Lentfer 	value = wpa_config_get(ssid, "group");
6006d49e1aeSJan Lentfer 	if (value == NULL)
6016d49e1aeSJan Lentfer 		return;
6026d49e1aeSJan Lentfer 	if (value[0])
6036d49e1aeSJan Lentfer 		fprintf(f, "\tgroup=%s\n", value);
6046d49e1aeSJan Lentfer 	os_free(value);
6056d49e1aeSJan Lentfer }
6066d49e1aeSJan Lentfer 
6076d49e1aeSJan Lentfer 
write_group_mgmt(FILE * f,struct wpa_ssid * ssid)608*a1157835SDaniel Fojt static void write_group_mgmt(FILE *f, struct wpa_ssid *ssid)
609*a1157835SDaniel Fojt {
610*a1157835SDaniel Fojt 	char *value;
611*a1157835SDaniel Fojt 
612*a1157835SDaniel Fojt 	if (!ssid->group_mgmt_cipher)
613*a1157835SDaniel Fojt 		return;
614*a1157835SDaniel Fojt 
615*a1157835SDaniel Fojt 	value = wpa_config_get(ssid, "group_mgmt");
616*a1157835SDaniel Fojt 	if (!value)
617*a1157835SDaniel Fojt 		return;
618*a1157835SDaniel Fojt 	if (value[0])
619*a1157835SDaniel Fojt 		fprintf(f, "\tgroup_mgmt=%s\n", value);
620*a1157835SDaniel Fojt 	os_free(value);
621*a1157835SDaniel Fojt }
622*a1157835SDaniel Fojt 
623*a1157835SDaniel Fojt 
write_auth_alg(FILE * f,struct wpa_ssid * ssid)6246d49e1aeSJan Lentfer static void write_auth_alg(FILE *f, struct wpa_ssid *ssid)
6256d49e1aeSJan Lentfer {
6266d49e1aeSJan Lentfer 	char *value;
6276d49e1aeSJan Lentfer 
6286d49e1aeSJan Lentfer 	if (ssid->auth_alg == 0)
6296d49e1aeSJan Lentfer 		return;
6306d49e1aeSJan Lentfer 
6316d49e1aeSJan Lentfer 	value = wpa_config_get(ssid, "auth_alg");
6326d49e1aeSJan Lentfer 	if (value == NULL)
6336d49e1aeSJan Lentfer 		return;
6346d49e1aeSJan Lentfer 	if (value[0])
6356d49e1aeSJan Lentfer 		fprintf(f, "\tauth_alg=%s\n", value);
6366d49e1aeSJan Lentfer 	os_free(value);
6376d49e1aeSJan Lentfer }
6386d49e1aeSJan Lentfer 
6396d49e1aeSJan Lentfer 
6406d49e1aeSJan Lentfer #ifdef IEEE8021X_EAPOL
write_eap(FILE * f,struct wpa_ssid * ssid)6416d49e1aeSJan Lentfer static void write_eap(FILE *f, struct wpa_ssid *ssid)
6426d49e1aeSJan Lentfer {
6436d49e1aeSJan Lentfer 	char *value;
6446d49e1aeSJan Lentfer 
6456d49e1aeSJan Lentfer 	value = wpa_config_get(ssid, "eap");
6466d49e1aeSJan Lentfer 	if (value == NULL)
6476d49e1aeSJan Lentfer 		return;
6486d49e1aeSJan Lentfer 
6496d49e1aeSJan Lentfer 	if (value[0])
6506d49e1aeSJan Lentfer 		fprintf(f, "\teap=%s\n", value);
6516d49e1aeSJan Lentfer 	os_free(value);
6526d49e1aeSJan Lentfer }
6536d49e1aeSJan Lentfer #endif /* IEEE8021X_EAPOL */
6546d49e1aeSJan Lentfer 
6556d49e1aeSJan Lentfer 
write_wep_key(FILE * f,int idx,struct wpa_ssid * ssid)6566d49e1aeSJan Lentfer static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid)
6576d49e1aeSJan Lentfer {
6586d49e1aeSJan Lentfer 	char field[20], *value;
6596d49e1aeSJan Lentfer 	int res;
6606d49e1aeSJan Lentfer 
6616d49e1aeSJan Lentfer 	res = os_snprintf(field, sizeof(field), "wep_key%d", idx);
662*a1157835SDaniel Fojt 	if (os_snprintf_error(sizeof(field), res))
6636d49e1aeSJan Lentfer 		return;
6646d49e1aeSJan Lentfer 	value = wpa_config_get(ssid, field);
6656d49e1aeSJan Lentfer 	if (value) {
6666d49e1aeSJan Lentfer 		fprintf(f, "\t%s=%s\n", field, value);
6676d49e1aeSJan Lentfer 		os_free(value);
6686d49e1aeSJan Lentfer 	}
6696d49e1aeSJan Lentfer }
6706d49e1aeSJan Lentfer 
6716d49e1aeSJan Lentfer 
6723ff40c12SJohn Marino #ifdef CONFIG_P2P
6733ff40c12SJohn Marino 
write_go_p2p_dev_addr(FILE * f,struct wpa_ssid * ssid)6743ff40c12SJohn Marino static void write_go_p2p_dev_addr(FILE *f, struct wpa_ssid *ssid)
6753ff40c12SJohn Marino {
6763ff40c12SJohn Marino 	char *value = wpa_config_get(ssid, "go_p2p_dev_addr");
6773ff40c12SJohn Marino 	if (value == NULL)
6783ff40c12SJohn Marino 		return;
6793ff40c12SJohn Marino 	fprintf(f, "\tgo_p2p_dev_addr=%s\n", value);
6803ff40c12SJohn Marino 	os_free(value);
6813ff40c12SJohn Marino }
6823ff40c12SJohn Marino 
write_p2p_client_list(FILE * f,struct wpa_ssid * ssid)6833ff40c12SJohn Marino static void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid)
6843ff40c12SJohn Marino {
6853ff40c12SJohn Marino 	char *value = wpa_config_get(ssid, "p2p_client_list");
6863ff40c12SJohn Marino 	if (value == NULL)
6873ff40c12SJohn Marino 		return;
6883ff40c12SJohn Marino 	fprintf(f, "\tp2p_client_list=%s\n", value);
6893ff40c12SJohn Marino 	os_free(value);
6903ff40c12SJohn Marino }
6913ff40c12SJohn Marino 
6923ff40c12SJohn Marino 
write_psk_list(FILE * f,struct wpa_ssid * ssid)6933ff40c12SJohn Marino static void write_psk_list(FILE *f, struct wpa_ssid *ssid)
6943ff40c12SJohn Marino {
6953ff40c12SJohn Marino 	struct psk_list_entry *psk;
6963ff40c12SJohn Marino 	char hex[32 * 2 + 1];
6973ff40c12SJohn Marino 
6983ff40c12SJohn Marino 	dl_list_for_each(psk, &ssid->psk_list, struct psk_list_entry, list) {
6993ff40c12SJohn Marino 		wpa_snprintf_hex(hex, sizeof(hex), psk->psk, sizeof(psk->psk));
7003ff40c12SJohn Marino 		fprintf(f, "\tpsk_list=%s" MACSTR "-%s\n",
7013ff40c12SJohn Marino 			psk->p2p ? "P2P-" : "", MAC2STR(psk->addr), hex);
7023ff40c12SJohn Marino 	}
7033ff40c12SJohn Marino }
7043ff40c12SJohn Marino 
7053ff40c12SJohn Marino #endif /* CONFIG_P2P */
7063ff40c12SJohn Marino 
7073ff40c12SJohn Marino 
708*a1157835SDaniel Fojt #ifdef CONFIG_MACSEC
709*a1157835SDaniel Fojt 
write_mka_cak(FILE * f,struct wpa_ssid * ssid)710*a1157835SDaniel Fojt static void write_mka_cak(FILE *f, struct wpa_ssid *ssid)
711*a1157835SDaniel Fojt {
712*a1157835SDaniel Fojt 	char *value;
713*a1157835SDaniel Fojt 
714*a1157835SDaniel Fojt 	if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK))
715*a1157835SDaniel Fojt 		return;
716*a1157835SDaniel Fojt 
717*a1157835SDaniel Fojt 	value = wpa_config_get(ssid, "mka_cak");
718*a1157835SDaniel Fojt 	if (!value)
719*a1157835SDaniel Fojt 		return;
720*a1157835SDaniel Fojt 	fprintf(f, "\tmka_cak=%s\n", value);
721*a1157835SDaniel Fojt 	os_free(value);
722*a1157835SDaniel Fojt }
723*a1157835SDaniel Fojt 
724*a1157835SDaniel Fojt 
write_mka_ckn(FILE * f,struct wpa_ssid * ssid)725*a1157835SDaniel Fojt static void write_mka_ckn(FILE *f, struct wpa_ssid *ssid)
726*a1157835SDaniel Fojt {
727*a1157835SDaniel Fojt 	char *value;
728*a1157835SDaniel Fojt 
729*a1157835SDaniel Fojt 	if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN))
730*a1157835SDaniel Fojt 		return;
731*a1157835SDaniel Fojt 
732*a1157835SDaniel Fojt 	value = wpa_config_get(ssid, "mka_ckn");
733*a1157835SDaniel Fojt 	if (!value)
734*a1157835SDaniel Fojt 		return;
735*a1157835SDaniel Fojt 	fprintf(f, "\tmka_ckn=%s\n", value);
736*a1157835SDaniel Fojt 	os_free(value);
737*a1157835SDaniel Fojt }
738*a1157835SDaniel Fojt 
739*a1157835SDaniel Fojt #endif /* CONFIG_MACSEC */
740*a1157835SDaniel Fojt 
741*a1157835SDaniel Fojt 
wpa_config_write_network(FILE * f,struct wpa_ssid * ssid)7426d49e1aeSJan Lentfer static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
7436d49e1aeSJan Lentfer {
7446d49e1aeSJan Lentfer 	int i;
7456d49e1aeSJan Lentfer 
7466d49e1aeSJan Lentfer #define STR(t) write_str(f, #t, ssid)
7476d49e1aeSJan Lentfer #define INT(t) write_int(f, #t, ssid->t, 0)
7486d49e1aeSJan Lentfer #define INTe(t) write_int(f, #t, ssid->eap.t, 0)
7496d49e1aeSJan Lentfer #define INT_DEF(t, def) write_int(f, #t, ssid->t, def)
7506d49e1aeSJan Lentfer #define INT_DEFe(t, def) write_int(f, #t, ssid->eap.t, def)
7516d49e1aeSJan Lentfer 
7526d49e1aeSJan Lentfer 	STR(ssid);
7536d49e1aeSJan Lentfer 	INT(scan_ssid);
7546d49e1aeSJan Lentfer 	write_bssid(f, ssid);
755*a1157835SDaniel Fojt 	write_bssid_hint(f, ssid);
756*a1157835SDaniel Fojt 	write_str(f, "bssid_blacklist", ssid);
757*a1157835SDaniel Fojt 	write_str(f, "bssid_whitelist", ssid);
7586d49e1aeSJan Lentfer 	write_psk(f, ssid);
759*a1157835SDaniel Fojt 	INT(mem_only_psk);
760*a1157835SDaniel Fojt 	STR(sae_password);
761*a1157835SDaniel Fojt 	STR(sae_password_id);
7626d49e1aeSJan Lentfer 	write_proto(f, ssid);
7636d49e1aeSJan Lentfer 	write_key_mgmt(f, ssid);
7643ff40c12SJohn Marino 	INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD);
7656d49e1aeSJan Lentfer 	write_pairwise(f, ssid);
7666d49e1aeSJan Lentfer 	write_group(f, ssid);
767*a1157835SDaniel Fojt 	write_group_mgmt(f, ssid);
7686d49e1aeSJan Lentfer 	write_auth_alg(f, ssid);
7693ff40c12SJohn Marino 	STR(bgscan);
7703ff40c12SJohn Marino 	STR(autoscan);
7713ff40c12SJohn Marino 	STR(scan_freq);
7726d49e1aeSJan Lentfer #ifdef IEEE8021X_EAPOL
7736d49e1aeSJan Lentfer 	write_eap(f, ssid);
7746d49e1aeSJan Lentfer 	STR(identity);
7756d49e1aeSJan Lentfer 	STR(anonymous_identity);
776*a1157835SDaniel Fojt 	STR(imsi_identity);
7776d49e1aeSJan Lentfer 	STR(password);
7786d49e1aeSJan Lentfer 	STR(ca_cert);
7796d49e1aeSJan Lentfer 	STR(ca_path);
7806d49e1aeSJan Lentfer 	STR(client_cert);
7816d49e1aeSJan Lentfer 	STR(private_key);
7826d49e1aeSJan Lentfer 	STR(private_key_passwd);
7836d49e1aeSJan Lentfer 	STR(dh_file);
7846d49e1aeSJan Lentfer 	STR(subject_match);
785*a1157835SDaniel Fojt 	STR(check_cert_subject);
7866d49e1aeSJan Lentfer 	STR(altsubject_match);
7873ff40c12SJohn Marino 	STR(domain_suffix_match);
788*a1157835SDaniel Fojt 	STR(domain_match);
7896d49e1aeSJan Lentfer 	STR(ca_cert2);
7906d49e1aeSJan Lentfer 	STR(ca_path2);
7916d49e1aeSJan Lentfer 	STR(client_cert2);
7926d49e1aeSJan Lentfer 	STR(private_key2);
7936d49e1aeSJan Lentfer 	STR(private_key2_passwd);
7946d49e1aeSJan Lentfer 	STR(dh_file2);
7956d49e1aeSJan Lentfer 	STR(subject_match2);
796*a1157835SDaniel Fojt 	STR(check_cert_subject2);
7976d49e1aeSJan Lentfer 	STR(altsubject_match2);
7983ff40c12SJohn Marino 	STR(domain_suffix_match2);
799*a1157835SDaniel Fojt 	STR(domain_match2);
8006d49e1aeSJan Lentfer 	STR(phase1);
8016d49e1aeSJan Lentfer 	STR(phase2);
8026d49e1aeSJan Lentfer 	STR(pcsc);
8036d49e1aeSJan Lentfer 	STR(pin);
8046d49e1aeSJan Lentfer 	STR(engine_id);
8056d49e1aeSJan Lentfer 	STR(key_id);
8066d49e1aeSJan Lentfer 	STR(cert_id);
8076d49e1aeSJan Lentfer 	STR(ca_cert_id);
8086d49e1aeSJan Lentfer 	STR(key2_id);
8096d49e1aeSJan Lentfer 	STR(pin2);
8106d49e1aeSJan Lentfer 	STR(engine2_id);
8116d49e1aeSJan Lentfer 	STR(cert2_id);
8126d49e1aeSJan Lentfer 	STR(ca_cert2_id);
8136d49e1aeSJan Lentfer 	INTe(engine);
8146d49e1aeSJan Lentfer 	INTe(engine2);
8156d49e1aeSJan Lentfer 	INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
816*a1157835SDaniel Fojt 	STR(openssl_ciphers);
817*a1157835SDaniel Fojt 	INTe(erp);
8186d49e1aeSJan Lentfer #endif /* IEEE8021X_EAPOL */
8196d49e1aeSJan Lentfer 	for (i = 0; i < 4; i++)
8206d49e1aeSJan Lentfer 		write_wep_key(f, i, ssid);
8216d49e1aeSJan Lentfer 	INT(wep_tx_keyidx);
8226d49e1aeSJan Lentfer 	INT(priority);
8236d49e1aeSJan Lentfer #ifdef IEEE8021X_EAPOL
8246d49e1aeSJan Lentfer 	INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND);
8256d49e1aeSJan Lentfer 	STR(pac_file);
8266d49e1aeSJan Lentfer 	INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE);
827*a1157835SDaniel Fojt 	INTe(ocsp);
828*a1157835SDaniel Fojt 	INT_DEFe(sim_num, DEFAULT_USER_SELECTED_SIM);
8296d49e1aeSJan Lentfer #endif /* IEEE8021X_EAPOL */
8306d49e1aeSJan Lentfer 	INT(mode);
831*a1157835SDaniel Fojt 	INT(no_auto_peer);
8323ff40c12SJohn Marino 	INT(frequency);
833*a1157835SDaniel Fojt 	INT(fixed_freq);
834*a1157835SDaniel Fojt #ifdef CONFIG_ACS
835*a1157835SDaniel Fojt 	INT(acs);
836*a1157835SDaniel Fojt #endif /* CONFIG_ACS */
8373ff40c12SJohn Marino 	write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1);
8386d49e1aeSJan Lentfer 	INT(disabled);
839*a1157835SDaniel Fojt 	INT(mixed_cell);
840*a1157835SDaniel Fojt 	INT(vht);
841*a1157835SDaniel Fojt 	INT_DEF(ht, 1);
842*a1157835SDaniel Fojt 	INT(ht40);
843*a1157835SDaniel Fojt 	INT_DEF(max_oper_chwidth, DEFAULT_MAX_OPER_CHWIDTH);
844*a1157835SDaniel Fojt 	INT(vht_center_freq1);
845*a1157835SDaniel Fojt 	INT(vht_center_freq2);
846*a1157835SDaniel Fojt 	INT(pbss);
847*a1157835SDaniel Fojt 	INT(wps_disabled);
848*a1157835SDaniel Fojt 	INT(fils_dh_group);
8496d49e1aeSJan Lentfer #ifdef CONFIG_IEEE80211W
8503ff40c12SJohn Marino 	write_int(f, "ieee80211w", ssid->ieee80211w,
8513ff40c12SJohn Marino 		  MGMT_FRAME_PROTECTION_DEFAULT);
8526d49e1aeSJan Lentfer #endif /* CONFIG_IEEE80211W */
8536d49e1aeSJan Lentfer 	STR(id_str);
8543ff40c12SJohn Marino #ifdef CONFIG_P2P
8553ff40c12SJohn Marino 	write_go_p2p_dev_addr(f, ssid);
8563ff40c12SJohn Marino 	write_p2p_client_list(f, ssid);
8573ff40c12SJohn Marino 	write_psk_list(f, ssid);
8583ff40c12SJohn Marino #endif /* CONFIG_P2P */
859*a1157835SDaniel Fojt 	INT(ap_max_inactivity);
8603ff40c12SJohn Marino 	INT(dtim_period);
8613ff40c12SJohn Marino 	INT(beacon_int);
862*a1157835SDaniel Fojt #ifdef CONFIG_MACSEC
863*a1157835SDaniel Fojt 	INT(macsec_policy);
864*a1157835SDaniel Fojt 	write_mka_cak(f, ssid);
865*a1157835SDaniel Fojt 	write_mka_ckn(f, ssid);
866*a1157835SDaniel Fojt 	INT(macsec_integ_only);
867*a1157835SDaniel Fojt 	INT(macsec_replay_protect);
868*a1157835SDaniel Fojt 	INT(macsec_replay_window);
869*a1157835SDaniel Fojt 	INT(macsec_port);
870*a1157835SDaniel Fojt 	INT_DEF(mka_priority, DEFAULT_PRIO_NOT_KEY_SERVER);
871*a1157835SDaniel Fojt #endif /* CONFIG_MACSEC */
872*a1157835SDaniel Fojt #ifdef CONFIG_HS20
873*a1157835SDaniel Fojt 	INT(update_identifier);
874*a1157835SDaniel Fojt 	STR(roaming_consortium_selection);
875*a1157835SDaniel Fojt #endif /* CONFIG_HS20 */
876*a1157835SDaniel Fojt 	write_int(f, "mac_addr", ssid->mac_addr, -1);
877*a1157835SDaniel Fojt #ifdef CONFIG_MESH
878*a1157835SDaniel Fojt 	STR(mesh_basic_rates);
879*a1157835SDaniel Fojt 	INT_DEF(dot11MeshMaxRetries, DEFAULT_MESH_MAX_RETRIES);
880*a1157835SDaniel Fojt 	INT_DEF(dot11MeshRetryTimeout, DEFAULT_MESH_RETRY_TIMEOUT);
881*a1157835SDaniel Fojt 	INT_DEF(dot11MeshConfirmTimeout, DEFAULT_MESH_CONFIRM_TIMEOUT);
882*a1157835SDaniel Fojt 	INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT);
883*a1157835SDaniel Fojt 	INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD);
884*a1157835SDaniel Fojt #endif /* CONFIG_MESH */
885*a1157835SDaniel Fojt 	INT(wpa_ptk_rekey);
886*a1157835SDaniel Fojt 	INT(group_rekey);
887*a1157835SDaniel Fojt 	INT(ignore_broadcast_ssid);
888*a1157835SDaniel Fojt #ifdef CONFIG_DPP
889*a1157835SDaniel Fojt 	STR(dpp_connector);
890*a1157835SDaniel Fojt 	STR(dpp_netaccesskey);
891*a1157835SDaniel Fojt 	INT(dpp_netaccesskey_expiry);
892*a1157835SDaniel Fojt 	STR(dpp_csign);
893*a1157835SDaniel Fojt #endif /* CONFIG_DPP */
894*a1157835SDaniel Fojt 	INT(owe_group);
895*a1157835SDaniel Fojt 	INT(owe_only);
896*a1157835SDaniel Fojt 	INT(multi_ap_backhaul_sta);
897*a1157835SDaniel Fojt 	INT(ft_eap_pmksa_caching);
898*a1157835SDaniel Fojt #ifdef CONFIG_HT_OVERRIDES
899*a1157835SDaniel Fojt 	INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
900*a1157835SDaniel Fojt 	INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40);
901*a1157835SDaniel Fojt 	INT_DEF(disable_sgi, DEFAULT_DISABLE_SGI);
902*a1157835SDaniel Fojt 	INT_DEF(disable_ldpc, DEFAULT_DISABLE_LDPC);
903*a1157835SDaniel Fojt 	INT(ht40_intolerant);
904*a1157835SDaniel Fojt 	INT_DEF(tx_stbc, DEFAULT_TX_STBC);
905*a1157835SDaniel Fojt 	INT_DEF(rx_stbc, DEFAULT_RX_STBC);
906*a1157835SDaniel Fojt 	INT_DEF(disable_max_amsdu, DEFAULT_DISABLE_MAX_AMSDU);
907*a1157835SDaniel Fojt 	INT_DEF(ampdu_factor, DEFAULT_AMPDU_FACTOR);
908*a1157835SDaniel Fojt 	INT_DEF(ampdu_density, DEFAULT_AMPDU_DENSITY);
909*a1157835SDaniel Fojt 	STR(ht_mcs);
910*a1157835SDaniel Fojt #endif /* CONFIG_HT_OVERRIDES */
911*a1157835SDaniel Fojt #ifdef CONFIG_VHT_OVERRIDES
912*a1157835SDaniel Fojt 	INT(disable_vht);
913*a1157835SDaniel Fojt 	INT(vht_capa);
914*a1157835SDaniel Fojt 	INT(vht_capa_mask);
915*a1157835SDaniel Fojt 	INT_DEF(vht_rx_mcs_nss_1, -1);
916*a1157835SDaniel Fojt 	INT_DEF(vht_rx_mcs_nss_2, -1);
917*a1157835SDaniel Fojt 	INT_DEF(vht_rx_mcs_nss_3, -1);
918*a1157835SDaniel Fojt 	INT_DEF(vht_rx_mcs_nss_4, -1);
919*a1157835SDaniel Fojt 	INT_DEF(vht_rx_mcs_nss_5, -1);
920*a1157835SDaniel Fojt 	INT_DEF(vht_rx_mcs_nss_6, -1);
921*a1157835SDaniel Fojt 	INT_DEF(vht_rx_mcs_nss_7, -1);
922*a1157835SDaniel Fojt 	INT_DEF(vht_rx_mcs_nss_8, -1);
923*a1157835SDaniel Fojt 	INT_DEF(vht_tx_mcs_nss_1, -1);
924*a1157835SDaniel Fojt 	INT_DEF(vht_tx_mcs_nss_2, -1);
925*a1157835SDaniel Fojt 	INT_DEF(vht_tx_mcs_nss_3, -1);
926*a1157835SDaniel Fojt 	INT_DEF(vht_tx_mcs_nss_4, -1);
927*a1157835SDaniel Fojt 	INT_DEF(vht_tx_mcs_nss_5, -1);
928*a1157835SDaniel Fojt 	INT_DEF(vht_tx_mcs_nss_6, -1);
929*a1157835SDaniel Fojt 	INT_DEF(vht_tx_mcs_nss_7, -1);
930*a1157835SDaniel Fojt 	INT_DEF(vht_tx_mcs_nss_8, -1);
931*a1157835SDaniel Fojt #endif /* CONFIG_VHT_OVERRIDES */
9326d49e1aeSJan Lentfer 
9336d49e1aeSJan Lentfer #undef STR
9346d49e1aeSJan Lentfer #undef INT
9356d49e1aeSJan Lentfer #undef INT_DEF
9366d49e1aeSJan Lentfer }
9376d49e1aeSJan Lentfer 
9386d49e1aeSJan Lentfer 
wpa_config_write_cred(FILE * f,struct wpa_cred * cred)9393ff40c12SJohn Marino static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
9403ff40c12SJohn Marino {
9413ff40c12SJohn Marino 	size_t i;
9423ff40c12SJohn Marino 
9433ff40c12SJohn Marino 	if (cred->priority)
9443ff40c12SJohn Marino 		fprintf(f, "\tpriority=%d\n", cred->priority);
9453ff40c12SJohn Marino 	if (cred->pcsc)
9463ff40c12SJohn Marino 		fprintf(f, "\tpcsc=%d\n", cred->pcsc);
9473ff40c12SJohn Marino 	if (cred->realm)
9483ff40c12SJohn Marino 		fprintf(f, "\trealm=\"%s\"\n", cred->realm);
9493ff40c12SJohn Marino 	if (cred->username)
9503ff40c12SJohn Marino 		fprintf(f, "\tusername=\"%s\"\n", cred->username);
9513ff40c12SJohn Marino 	if (cred->password && cred->ext_password)
9523ff40c12SJohn Marino 		fprintf(f, "\tpassword=ext:%s\n", cred->password);
9533ff40c12SJohn Marino 	else if (cred->password)
9543ff40c12SJohn Marino 		fprintf(f, "\tpassword=\"%s\"\n", cred->password);
9553ff40c12SJohn Marino 	if (cred->ca_cert)
9563ff40c12SJohn Marino 		fprintf(f, "\tca_cert=\"%s\"\n", cred->ca_cert);
9573ff40c12SJohn Marino 	if (cred->client_cert)
9583ff40c12SJohn Marino 		fprintf(f, "\tclient_cert=\"%s\"\n", cred->client_cert);
9593ff40c12SJohn Marino 	if (cred->private_key)
9603ff40c12SJohn Marino 		fprintf(f, "\tprivate_key=\"%s\"\n", cred->private_key);
9613ff40c12SJohn Marino 	if (cred->private_key_passwd)
9623ff40c12SJohn Marino 		fprintf(f, "\tprivate_key_passwd=\"%s\"\n",
9633ff40c12SJohn Marino 			cred->private_key_passwd);
9643ff40c12SJohn Marino 	if (cred->imsi)
9653ff40c12SJohn Marino 		fprintf(f, "\timsi=\"%s\"\n", cred->imsi);
9663ff40c12SJohn Marino 	if (cred->milenage)
9673ff40c12SJohn Marino 		fprintf(f, "\tmilenage=\"%s\"\n", cred->milenage);
9683ff40c12SJohn Marino 	for (i = 0; i < cred->num_domain; i++)
9693ff40c12SJohn Marino 		fprintf(f, "\tdomain=\"%s\"\n", cred->domain[i]);
9703ff40c12SJohn Marino 	if (cred->domain_suffix_match)
971*a1157835SDaniel Fojt 		fprintf(f, "\tdomain_suffix_match=\"%s\"\n",
9723ff40c12SJohn Marino 			cred->domain_suffix_match);
9733ff40c12SJohn Marino 	if (cred->roaming_consortium_len) {
9743ff40c12SJohn Marino 		fprintf(f, "\troaming_consortium=");
9753ff40c12SJohn Marino 		for (i = 0; i < cred->roaming_consortium_len; i++)
9763ff40c12SJohn Marino 			fprintf(f, "%02x", cred->roaming_consortium[i]);
9773ff40c12SJohn Marino 		fprintf(f, "\n");
9783ff40c12SJohn Marino 	}
9793ff40c12SJohn Marino 	if (cred->eap_method) {
9803ff40c12SJohn Marino 		const char *name;
9813ff40c12SJohn Marino 		name = eap_get_name(cred->eap_method[0].vendor,
9823ff40c12SJohn Marino 				    cred->eap_method[0].method);
983*a1157835SDaniel Fojt 		if (name)
9843ff40c12SJohn Marino 			fprintf(f, "\teap=%s\n", name);
9853ff40c12SJohn Marino 	}
9863ff40c12SJohn Marino 	if (cred->phase1)
9873ff40c12SJohn Marino 		fprintf(f, "\tphase1=\"%s\"\n", cred->phase1);
9883ff40c12SJohn Marino 	if (cred->phase2)
9893ff40c12SJohn Marino 		fprintf(f, "\tphase2=\"%s\"\n", cred->phase2);
9903ff40c12SJohn Marino 	if (cred->excluded_ssid) {
9913ff40c12SJohn Marino 		size_t j;
9923ff40c12SJohn Marino 		for (i = 0; i < cred->num_excluded_ssid; i++) {
9933ff40c12SJohn Marino 			struct excluded_ssid *e = &cred->excluded_ssid[i];
9943ff40c12SJohn Marino 			fprintf(f, "\texcluded_ssid=");
9953ff40c12SJohn Marino 			for (j = 0; j < e->ssid_len; j++)
9963ff40c12SJohn Marino 				fprintf(f, "%02x", e->ssid[j]);
9973ff40c12SJohn Marino 			fprintf(f, "\n");
9983ff40c12SJohn Marino 		}
9993ff40c12SJohn Marino 	}
1000*a1157835SDaniel Fojt 	if (cred->roaming_partner) {
1001*a1157835SDaniel Fojt 		for (i = 0; i < cred->num_roaming_partner; i++) {
1002*a1157835SDaniel Fojt 			struct roaming_partner *p = &cred->roaming_partner[i];
1003*a1157835SDaniel Fojt 			fprintf(f, "\troaming_partner=\"%s,%d,%u,%s\"\n",
1004*a1157835SDaniel Fojt 				p->fqdn, p->exact_match, p->priority,
1005*a1157835SDaniel Fojt 				p->country);
1006*a1157835SDaniel Fojt 		}
1007*a1157835SDaniel Fojt 	}
1008*a1157835SDaniel Fojt 	if (cred->update_identifier)
1009*a1157835SDaniel Fojt 		fprintf(f, "\tupdate_identifier=%d\n", cred->update_identifier);
1010*a1157835SDaniel Fojt 
1011*a1157835SDaniel Fojt 	if (cred->provisioning_sp)
1012*a1157835SDaniel Fojt 		fprintf(f, "\tprovisioning_sp=\"%s\"\n", cred->provisioning_sp);
1013*a1157835SDaniel Fojt 	if (cred->sp_priority)
1014*a1157835SDaniel Fojt 		fprintf(f, "\tsp_priority=%d\n", cred->sp_priority);
1015*a1157835SDaniel Fojt 
1016*a1157835SDaniel Fojt 	if (cred->min_dl_bandwidth_home)
1017*a1157835SDaniel Fojt 		fprintf(f, "\tmin_dl_bandwidth_home=%u\n",
1018*a1157835SDaniel Fojt 			cred->min_dl_bandwidth_home);
1019*a1157835SDaniel Fojt 	if (cred->min_ul_bandwidth_home)
1020*a1157835SDaniel Fojt 		fprintf(f, "\tmin_ul_bandwidth_home=%u\n",
1021*a1157835SDaniel Fojt 			cred->min_ul_bandwidth_home);
1022*a1157835SDaniel Fojt 	if (cred->min_dl_bandwidth_roaming)
1023*a1157835SDaniel Fojt 		fprintf(f, "\tmin_dl_bandwidth_roaming=%u\n",
1024*a1157835SDaniel Fojt 			cred->min_dl_bandwidth_roaming);
1025*a1157835SDaniel Fojt 	if (cred->min_ul_bandwidth_roaming)
1026*a1157835SDaniel Fojt 		fprintf(f, "\tmin_ul_bandwidth_roaming=%u\n",
1027*a1157835SDaniel Fojt 			cred->min_ul_bandwidth_roaming);
1028*a1157835SDaniel Fojt 
1029*a1157835SDaniel Fojt 	if (cred->max_bss_load)
1030*a1157835SDaniel Fojt 		fprintf(f, "\tmax_bss_load=%u\n",
1031*a1157835SDaniel Fojt 			cred->max_bss_load);
1032*a1157835SDaniel Fojt 
1033*a1157835SDaniel Fojt 	if (cred->ocsp)
1034*a1157835SDaniel Fojt 		fprintf(f, "\tocsp=%d\n", cred->ocsp);
1035*a1157835SDaniel Fojt 
1036*a1157835SDaniel Fojt 	if (cred->num_req_conn_capab) {
1037*a1157835SDaniel Fojt 		for (i = 0; i < cred->num_req_conn_capab; i++) {
1038*a1157835SDaniel Fojt 			int *ports;
1039*a1157835SDaniel Fojt 
1040*a1157835SDaniel Fojt 			fprintf(f, "\treq_conn_capab=%u",
1041*a1157835SDaniel Fojt 				cred->req_conn_capab_proto[i]);
1042*a1157835SDaniel Fojt 			ports = cred->req_conn_capab_port[i];
1043*a1157835SDaniel Fojt 			if (ports) {
1044*a1157835SDaniel Fojt 				int j;
1045*a1157835SDaniel Fojt 				for (j = 0; ports[j] != -1; j++) {
1046*a1157835SDaniel Fojt 					fprintf(f, "%s%d", j > 0 ? "," : ":",
1047*a1157835SDaniel Fojt 						ports[j]);
1048*a1157835SDaniel Fojt 				}
1049*a1157835SDaniel Fojt 			}
1050*a1157835SDaniel Fojt 			fprintf(f, "\n");
1051*a1157835SDaniel Fojt 		}
1052*a1157835SDaniel Fojt 	}
1053*a1157835SDaniel Fojt 
1054*a1157835SDaniel Fojt 	if (cred->required_roaming_consortium_len) {
1055*a1157835SDaniel Fojt 		fprintf(f, "\trequired_roaming_consortium=");
1056*a1157835SDaniel Fojt 		for (i = 0; i < cred->required_roaming_consortium_len; i++)
1057*a1157835SDaniel Fojt 			fprintf(f, "%02x",
1058*a1157835SDaniel Fojt 				cred->required_roaming_consortium[i]);
1059*a1157835SDaniel Fojt 		fprintf(f, "\n");
1060*a1157835SDaniel Fojt 	}
1061*a1157835SDaniel Fojt 
1062*a1157835SDaniel Fojt 	if (cred->num_roaming_consortiums) {
1063*a1157835SDaniel Fojt 		size_t j;
1064*a1157835SDaniel Fojt 
1065*a1157835SDaniel Fojt 		fprintf(f, "\troaming_consortiums=\"");
1066*a1157835SDaniel Fojt 		for (i = 0; i < cred->num_roaming_consortiums; i++) {
1067*a1157835SDaniel Fojt 			if (i > 0)
1068*a1157835SDaniel Fojt 				fprintf(f, ",");
1069*a1157835SDaniel Fojt 			for (j = 0; j < cred->roaming_consortiums_len[i]; j++)
1070*a1157835SDaniel Fojt 				fprintf(f, "%02x",
1071*a1157835SDaniel Fojt 					cred->roaming_consortiums[i][j]);
1072*a1157835SDaniel Fojt 		}
1073*a1157835SDaniel Fojt 		fprintf(f, "\"\n");
1074*a1157835SDaniel Fojt 	}
1075*a1157835SDaniel Fojt 
1076*a1157835SDaniel Fojt 	if (cred->sim_num != DEFAULT_USER_SELECTED_SIM)
1077*a1157835SDaniel Fojt 		fprintf(f, "\tsim_num=%d\n", cred->sim_num);
10783ff40c12SJohn Marino }
10793ff40c12SJohn Marino 
10803ff40c12SJohn Marino 
10816d49e1aeSJan Lentfer #ifndef CONFIG_NO_CONFIG_BLOBS
wpa_config_write_blob(FILE * f,struct wpa_config_blob * blob)10826d49e1aeSJan Lentfer static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob)
10836d49e1aeSJan Lentfer {
10846d49e1aeSJan Lentfer 	unsigned char *encoded;
10856d49e1aeSJan Lentfer 
10866d49e1aeSJan Lentfer 	encoded = base64_encode(blob->data, blob->len, NULL);
10876d49e1aeSJan Lentfer 	if (encoded == NULL)
10886d49e1aeSJan Lentfer 		return -1;
10896d49e1aeSJan Lentfer 
10906d49e1aeSJan Lentfer 	fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded);
10916d49e1aeSJan Lentfer 	os_free(encoded);
10926d49e1aeSJan Lentfer 	return 0;
10936d49e1aeSJan Lentfer }
10946d49e1aeSJan Lentfer #endif /* CONFIG_NO_CONFIG_BLOBS */
10956d49e1aeSJan Lentfer 
10966d49e1aeSJan Lentfer 
write_global_bin(FILE * f,const char * field,const struct wpabuf * val)10973ff40c12SJohn Marino static void write_global_bin(FILE *f, const char *field,
10983ff40c12SJohn Marino 			     const struct wpabuf *val)
10993ff40c12SJohn Marino {
11003ff40c12SJohn Marino 	size_t i;
11013ff40c12SJohn Marino 	const u8 *pos;
11023ff40c12SJohn Marino 
11033ff40c12SJohn Marino 	if (val == NULL)
11043ff40c12SJohn Marino 		return;
11053ff40c12SJohn Marino 
11063ff40c12SJohn Marino 	fprintf(f, "%s=", field);
11073ff40c12SJohn Marino 	pos = wpabuf_head(val);
11083ff40c12SJohn Marino 	for (i = 0; i < wpabuf_len(val); i++)
11093ff40c12SJohn Marino 		fprintf(f, "%02X", *pos++);
11103ff40c12SJohn Marino 	fprintf(f, "\n");
11113ff40c12SJohn Marino }
11123ff40c12SJohn Marino 
11133ff40c12SJohn Marino 
wpa_config_write_global(FILE * f,struct wpa_config * config)11146d49e1aeSJan Lentfer static void wpa_config_write_global(FILE *f, struct wpa_config *config)
11156d49e1aeSJan Lentfer {
11166d49e1aeSJan Lentfer #ifdef CONFIG_CTRL_IFACE
11176d49e1aeSJan Lentfer 	if (config->ctrl_interface)
11186d49e1aeSJan Lentfer 		fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface);
11196d49e1aeSJan Lentfer 	if (config->ctrl_interface_group)
11206d49e1aeSJan Lentfer 		fprintf(f, "ctrl_interface_group=%s\n",
11216d49e1aeSJan Lentfer 			config->ctrl_interface_group);
11226d49e1aeSJan Lentfer #endif /* CONFIG_CTRL_IFACE */
11236d49e1aeSJan Lentfer 	if (config->eapol_version != DEFAULT_EAPOL_VERSION)
11246d49e1aeSJan Lentfer 		fprintf(f, "eapol_version=%d\n", config->eapol_version);
11256d49e1aeSJan Lentfer 	if (config->ap_scan != DEFAULT_AP_SCAN)
11266d49e1aeSJan Lentfer 		fprintf(f, "ap_scan=%d\n", config->ap_scan);
11273ff40c12SJohn Marino 	if (config->disable_scan_offload)
11283ff40c12SJohn Marino 		fprintf(f, "disable_scan_offload=%d\n",
11293ff40c12SJohn Marino 			config->disable_scan_offload);
11306d49e1aeSJan Lentfer 	if (config->fast_reauth != DEFAULT_FAST_REAUTH)
11316d49e1aeSJan Lentfer 		fprintf(f, "fast_reauth=%d\n", config->fast_reauth);
11326d49e1aeSJan Lentfer 	if (config->opensc_engine_path)
11336d49e1aeSJan Lentfer 		fprintf(f, "opensc_engine_path=%s\n",
11346d49e1aeSJan Lentfer 			config->opensc_engine_path);
11356d49e1aeSJan Lentfer 	if (config->pkcs11_engine_path)
11366d49e1aeSJan Lentfer 		fprintf(f, "pkcs11_engine_path=%s\n",
11376d49e1aeSJan Lentfer 			config->pkcs11_engine_path);
11386d49e1aeSJan Lentfer 	if (config->pkcs11_module_path)
11396d49e1aeSJan Lentfer 		fprintf(f, "pkcs11_module_path=%s\n",
11406d49e1aeSJan Lentfer 			config->pkcs11_module_path);
1141*a1157835SDaniel Fojt 	if (config->openssl_ciphers)
1142*a1157835SDaniel Fojt 		fprintf(f, "openssl_ciphers=%s\n", config->openssl_ciphers);
11433ff40c12SJohn Marino 	if (config->pcsc_reader)
11443ff40c12SJohn Marino 		fprintf(f, "pcsc_reader=%s\n", config->pcsc_reader);
11453ff40c12SJohn Marino 	if (config->pcsc_pin)
11463ff40c12SJohn Marino 		fprintf(f, "pcsc_pin=%s\n", config->pcsc_pin);
11476d49e1aeSJan Lentfer 	if (config->driver_param)
11486d49e1aeSJan Lentfer 		fprintf(f, "driver_param=%s\n", config->driver_param);
11496d49e1aeSJan Lentfer 	if (config->dot11RSNAConfigPMKLifetime)
1150*a1157835SDaniel Fojt 		fprintf(f, "dot11RSNAConfigPMKLifetime=%u\n",
11516d49e1aeSJan Lentfer 			config->dot11RSNAConfigPMKLifetime);
11526d49e1aeSJan Lentfer 	if (config->dot11RSNAConfigPMKReauthThreshold)
1153*a1157835SDaniel Fojt 		fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%u\n",
11546d49e1aeSJan Lentfer 			config->dot11RSNAConfigPMKReauthThreshold);
11556d49e1aeSJan Lentfer 	if (config->dot11RSNAConfigSATimeout)
1156*a1157835SDaniel Fojt 		fprintf(f, "dot11RSNAConfigSATimeout=%u\n",
11576d49e1aeSJan Lentfer 			config->dot11RSNAConfigSATimeout);
11586d49e1aeSJan Lentfer 	if (config->update_config)
11596d49e1aeSJan Lentfer 		fprintf(f, "update_config=%d\n", config->update_config);
11606d49e1aeSJan Lentfer #ifdef CONFIG_WPS
11616d49e1aeSJan Lentfer 	if (!is_nil_uuid(config->uuid)) {
11626d49e1aeSJan Lentfer 		char buf[40];
11636d49e1aeSJan Lentfer 		uuid_bin2str(config->uuid, buf, sizeof(buf));
11646d49e1aeSJan Lentfer 		fprintf(f, "uuid=%s\n", buf);
11656d49e1aeSJan Lentfer 	}
1166*a1157835SDaniel Fojt 	if (config->auto_uuid)
1167*a1157835SDaniel Fojt 		fprintf(f, "auto_uuid=%d\n", config->auto_uuid);
11686d49e1aeSJan Lentfer 	if (config->device_name)
11696d49e1aeSJan Lentfer 		fprintf(f, "device_name=%s\n", config->device_name);
11706d49e1aeSJan Lentfer 	if (config->manufacturer)
11716d49e1aeSJan Lentfer 		fprintf(f, "manufacturer=%s\n", config->manufacturer);
11726d49e1aeSJan Lentfer 	if (config->model_name)
11736d49e1aeSJan Lentfer 		fprintf(f, "model_name=%s\n", config->model_name);
11746d49e1aeSJan Lentfer 	if (config->model_number)
11756d49e1aeSJan Lentfer 		fprintf(f, "model_number=%s\n", config->model_number);
11766d49e1aeSJan Lentfer 	if (config->serial_number)
11776d49e1aeSJan Lentfer 		fprintf(f, "serial_number=%s\n", config->serial_number);
11783ff40c12SJohn Marino 	{
11793ff40c12SJohn Marino 		char _buf[WPS_DEV_TYPE_BUFSIZE], *buf;
11803ff40c12SJohn Marino 		buf = wps_dev_type_bin2str(config->device_type,
11813ff40c12SJohn Marino 					   _buf, sizeof(_buf));
11823ff40c12SJohn Marino 		if (os_strcmp(buf, "0-00000000-0") != 0)
11833ff40c12SJohn Marino 			fprintf(f, "device_type=%s\n", buf);
11843ff40c12SJohn Marino 	}
11856d49e1aeSJan Lentfer 	if (WPA_GET_BE32(config->os_version))
11866d49e1aeSJan Lentfer 		fprintf(f, "os_version=%08x\n",
11876d49e1aeSJan Lentfer 			WPA_GET_BE32(config->os_version));
11883ff40c12SJohn Marino 	if (config->config_methods)
11893ff40c12SJohn Marino 		fprintf(f, "config_methods=%s\n", config->config_methods);
11906d49e1aeSJan Lentfer 	if (config->wps_cred_processing)
11916d49e1aeSJan Lentfer 		fprintf(f, "wps_cred_processing=%d\n",
11926d49e1aeSJan Lentfer 			config->wps_cred_processing);
1193*a1157835SDaniel Fojt 	if (config->wps_cred_add_sae)
1194*a1157835SDaniel Fojt 		fprintf(f, "wps_cred_add_sae=%d\n",
1195*a1157835SDaniel Fojt 			config->wps_cred_add_sae);
11963ff40c12SJohn Marino 	if (config->wps_vendor_ext_m1) {
11973ff40c12SJohn Marino 		int i, len = wpabuf_len(config->wps_vendor_ext_m1);
11983ff40c12SJohn Marino 		const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1);
11993ff40c12SJohn Marino 		if (len > 0) {
12003ff40c12SJohn Marino 			fprintf(f, "wps_vendor_ext_m1=");
12013ff40c12SJohn Marino 			for (i = 0; i < len; i++)
12023ff40c12SJohn Marino 				fprintf(f, "%02x", *p++);
12033ff40c12SJohn Marino 			fprintf(f, "\n");
12043ff40c12SJohn Marino 		}
12053ff40c12SJohn Marino 	}
12066d49e1aeSJan Lentfer #endif /* CONFIG_WPS */
12073ff40c12SJohn Marino #ifdef CONFIG_P2P
1208*a1157835SDaniel Fojt 	{
1209*a1157835SDaniel Fojt 		int i;
1210*a1157835SDaniel Fojt 		char _buf[WPS_DEV_TYPE_BUFSIZE], *buf;
1211*a1157835SDaniel Fojt 
1212*a1157835SDaniel Fojt 		for (i = 0; i < config->num_sec_device_types; i++) {
1213*a1157835SDaniel Fojt 			buf = wps_dev_type_bin2str(config->sec_device_type[i],
1214*a1157835SDaniel Fojt 						   _buf, sizeof(_buf));
1215*a1157835SDaniel Fojt 			if (buf)
1216*a1157835SDaniel Fojt 				fprintf(f, "sec_device_type=%s\n", buf);
1217*a1157835SDaniel Fojt 		}
1218*a1157835SDaniel Fojt 	}
12193ff40c12SJohn Marino 	if (config->p2p_listen_reg_class)
1220*a1157835SDaniel Fojt 		fprintf(f, "p2p_listen_reg_class=%d\n",
12213ff40c12SJohn Marino 			config->p2p_listen_reg_class);
12223ff40c12SJohn Marino 	if (config->p2p_listen_channel)
1223*a1157835SDaniel Fojt 		fprintf(f, "p2p_listen_channel=%d\n",
12243ff40c12SJohn Marino 			config->p2p_listen_channel);
12253ff40c12SJohn Marino 	if (config->p2p_oper_reg_class)
1226*a1157835SDaniel Fojt 		fprintf(f, "p2p_oper_reg_class=%d\n",
12273ff40c12SJohn Marino 			config->p2p_oper_reg_class);
12283ff40c12SJohn Marino 	if (config->p2p_oper_channel)
1229*a1157835SDaniel Fojt 		fprintf(f, "p2p_oper_channel=%d\n", config->p2p_oper_channel);
12303ff40c12SJohn Marino 	if (config->p2p_go_intent != DEFAULT_P2P_GO_INTENT)
1231*a1157835SDaniel Fojt 		fprintf(f, "p2p_go_intent=%d\n", config->p2p_go_intent);
12323ff40c12SJohn Marino 	if (config->p2p_ssid_postfix)
12333ff40c12SJohn Marino 		fprintf(f, "p2p_ssid_postfix=%s\n", config->p2p_ssid_postfix);
12343ff40c12SJohn Marino 	if (config->persistent_reconnect)
1235*a1157835SDaniel Fojt 		fprintf(f, "persistent_reconnect=%d\n",
12363ff40c12SJohn Marino 			config->persistent_reconnect);
12373ff40c12SJohn Marino 	if (config->p2p_intra_bss != DEFAULT_P2P_INTRA_BSS)
1238*a1157835SDaniel Fojt 		fprintf(f, "p2p_intra_bss=%d\n", config->p2p_intra_bss);
12393ff40c12SJohn Marino 	if (config->p2p_group_idle)
1240*a1157835SDaniel Fojt 		fprintf(f, "p2p_group_idle=%d\n", config->p2p_group_idle);
1241*a1157835SDaniel Fojt 	if (config->p2p_passphrase_len)
1242*a1157835SDaniel Fojt 		fprintf(f, "p2p_passphrase_len=%u\n",
1243*a1157835SDaniel Fojt 			config->p2p_passphrase_len);
12443ff40c12SJohn Marino 	if (config->p2p_pref_chan) {
12453ff40c12SJohn Marino 		unsigned int i;
12463ff40c12SJohn Marino 		fprintf(f, "p2p_pref_chan=");
12473ff40c12SJohn Marino 		for (i = 0; i < config->num_p2p_pref_chan; i++) {
12483ff40c12SJohn Marino 			fprintf(f, "%s%u:%u", i > 0 ? "," : "",
12493ff40c12SJohn Marino 				config->p2p_pref_chan[i].op_class,
12503ff40c12SJohn Marino 				config->p2p_pref_chan[i].chan);
12513ff40c12SJohn Marino 		}
12523ff40c12SJohn Marino 		fprintf(f, "\n");
12533ff40c12SJohn Marino 	}
12543ff40c12SJohn Marino 	if (config->p2p_no_go_freq.num) {
12553ff40c12SJohn Marino 		char *val = freq_range_list_str(&config->p2p_no_go_freq);
12563ff40c12SJohn Marino 		if (val) {
12573ff40c12SJohn Marino 			fprintf(f, "p2p_no_go_freq=%s\n", val);
12583ff40c12SJohn Marino 			os_free(val);
12593ff40c12SJohn Marino 		}
12603ff40c12SJohn Marino 	}
12613ff40c12SJohn Marino 	if (config->p2p_add_cli_chan)
12623ff40c12SJohn Marino 		fprintf(f, "p2p_add_cli_chan=%d\n", config->p2p_add_cli_chan);
1263*a1157835SDaniel Fojt 	if (config->p2p_optimize_listen_chan !=
1264*a1157835SDaniel Fojt 	    DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN)
1265*a1157835SDaniel Fojt 		fprintf(f, "p2p_optimize_listen_chan=%d\n",
1266*a1157835SDaniel Fojt 			config->p2p_optimize_listen_chan);
12673ff40c12SJohn Marino 	if (config->p2p_go_ht40)
1268*a1157835SDaniel Fojt 		fprintf(f, "p2p_go_ht40=%d\n", config->p2p_go_ht40);
12693ff40c12SJohn Marino 	if (config->p2p_go_vht)
1270*a1157835SDaniel Fojt 		fprintf(f, "p2p_go_vht=%d\n", config->p2p_go_vht);
1271*a1157835SDaniel Fojt 	if (config->p2p_go_he)
1272*a1157835SDaniel Fojt 		fprintf(f, "p2p_go_he=%d\n", config->p2p_go_he);
1273*a1157835SDaniel Fojt 	if (config->p2p_go_ctwindow != DEFAULT_P2P_GO_CTWINDOW)
1274*a1157835SDaniel Fojt 		fprintf(f, "p2p_go_ctwindow=%d\n", config->p2p_go_ctwindow);
12753ff40c12SJohn Marino 	if (config->p2p_disabled)
1276*a1157835SDaniel Fojt 		fprintf(f, "p2p_disabled=%d\n", config->p2p_disabled);
12773ff40c12SJohn Marino 	if (config->p2p_no_group_iface)
1278*a1157835SDaniel Fojt 		fprintf(f, "p2p_no_group_iface=%d\n",
12793ff40c12SJohn Marino 			config->p2p_no_group_iface);
12803ff40c12SJohn Marino 	if (config->p2p_ignore_shared_freq)
1281*a1157835SDaniel Fojt 		fprintf(f, "p2p_ignore_shared_freq=%d\n",
12823ff40c12SJohn Marino 			config->p2p_ignore_shared_freq);
1283*a1157835SDaniel Fojt 	if (config->p2p_cli_probe)
1284*a1157835SDaniel Fojt 		fprintf(f, "p2p_cli_probe=%d\n", config->p2p_cli_probe);
1285*a1157835SDaniel Fojt 	if (config->p2p_go_freq_change_policy != DEFAULT_P2P_GO_FREQ_MOVE)
1286*a1157835SDaniel Fojt 		fprintf(f, "p2p_go_freq_change_policy=%u\n",
1287*a1157835SDaniel Fojt 			config->p2p_go_freq_change_policy);
1288*a1157835SDaniel Fojt 	if (WPA_GET_BE32(config->ip_addr_go))
1289*a1157835SDaniel Fojt 		fprintf(f, "ip_addr_go=%u.%u.%u.%u\n",
1290*a1157835SDaniel Fojt 			config->ip_addr_go[0], config->ip_addr_go[1],
1291*a1157835SDaniel Fojt 			config->ip_addr_go[2], config->ip_addr_go[3]);
1292*a1157835SDaniel Fojt 	if (WPA_GET_BE32(config->ip_addr_mask))
1293*a1157835SDaniel Fojt 		fprintf(f, "ip_addr_mask=%u.%u.%u.%u\n",
1294*a1157835SDaniel Fojt 			config->ip_addr_mask[0], config->ip_addr_mask[1],
1295*a1157835SDaniel Fojt 			config->ip_addr_mask[2], config->ip_addr_mask[3]);
1296*a1157835SDaniel Fojt 	if (WPA_GET_BE32(config->ip_addr_start))
1297*a1157835SDaniel Fojt 		fprintf(f, "ip_addr_start=%u.%u.%u.%u\n",
1298*a1157835SDaniel Fojt 			config->ip_addr_start[0], config->ip_addr_start[1],
1299*a1157835SDaniel Fojt 			config->ip_addr_start[2], config->ip_addr_start[3]);
1300*a1157835SDaniel Fojt 	if (WPA_GET_BE32(config->ip_addr_end))
1301*a1157835SDaniel Fojt 		fprintf(f, "ip_addr_end=%u.%u.%u.%u\n",
1302*a1157835SDaniel Fojt 			config->ip_addr_end[0], config->ip_addr_end[1],
1303*a1157835SDaniel Fojt 			config->ip_addr_end[2], config->ip_addr_end[3]);
13043ff40c12SJohn Marino #endif /* CONFIG_P2P */
13056d49e1aeSJan Lentfer 	if (config->country[0] && config->country[1]) {
13066d49e1aeSJan Lentfer 		fprintf(f, "country=%c%c\n",
13076d49e1aeSJan Lentfer 			config->country[0], config->country[1]);
13086d49e1aeSJan Lentfer 	}
13093ff40c12SJohn Marino 	if (config->bss_max_count != DEFAULT_BSS_MAX_COUNT)
13103ff40c12SJohn Marino 		fprintf(f, "bss_max_count=%u\n", config->bss_max_count);
13113ff40c12SJohn Marino 	if (config->bss_expiration_age != DEFAULT_BSS_EXPIRATION_AGE)
13123ff40c12SJohn Marino 		fprintf(f, "bss_expiration_age=%u\n",
13133ff40c12SJohn Marino 			config->bss_expiration_age);
13143ff40c12SJohn Marino 	if (config->bss_expiration_scan_count !=
13153ff40c12SJohn Marino 	    DEFAULT_BSS_EXPIRATION_SCAN_COUNT)
13163ff40c12SJohn Marino 		fprintf(f, "bss_expiration_scan_count=%u\n",
13173ff40c12SJohn Marino 			config->bss_expiration_scan_count);
13183ff40c12SJohn Marino 	if (config->filter_ssids)
13193ff40c12SJohn Marino 		fprintf(f, "filter_ssids=%d\n", config->filter_ssids);
1320*a1157835SDaniel Fojt 	if (config->filter_rssi)
1321*a1157835SDaniel Fojt 		fprintf(f, "filter_rssi=%d\n", config->filter_rssi);
13223ff40c12SJohn Marino 	if (config->max_num_sta != DEFAULT_MAX_NUM_STA)
13233ff40c12SJohn Marino 		fprintf(f, "max_num_sta=%u\n", config->max_num_sta);
1324*a1157835SDaniel Fojt 	if (config->ap_isolate != DEFAULT_AP_ISOLATE)
1325*a1157835SDaniel Fojt 		fprintf(f, "ap_isolate=%u\n", config->ap_isolate);
13263ff40c12SJohn Marino 	if (config->disassoc_low_ack)
1327*a1157835SDaniel Fojt 		fprintf(f, "disassoc_low_ack=%d\n", config->disassoc_low_ack);
13283ff40c12SJohn Marino #ifdef CONFIG_HS20
13293ff40c12SJohn Marino 	if (config->hs20)
13303ff40c12SJohn Marino 		fprintf(f, "hs20=1\n");
13313ff40c12SJohn Marino #endif /* CONFIG_HS20 */
13323ff40c12SJohn Marino #ifdef CONFIG_INTERWORKING
13333ff40c12SJohn Marino 	if (config->interworking)
1334*a1157835SDaniel Fojt 		fprintf(f, "interworking=%d\n", config->interworking);
13353ff40c12SJohn Marino 	if (!is_zero_ether_addr(config->hessid))
13363ff40c12SJohn Marino 		fprintf(f, "hessid=" MACSTR "\n", MAC2STR(config->hessid));
13373ff40c12SJohn Marino 	if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE)
13383ff40c12SJohn Marino 		fprintf(f, "access_network_type=%d\n",
13393ff40c12SJohn Marino 			config->access_network_type);
1340*a1157835SDaniel Fojt 	if (config->go_interworking)
1341*a1157835SDaniel Fojt 		fprintf(f, "go_interworking=%d\n", config->go_interworking);
1342*a1157835SDaniel Fojt 	if (config->go_access_network_type)
1343*a1157835SDaniel Fojt 		fprintf(f, "go_access_network_type=%d\n",
1344*a1157835SDaniel Fojt 			config->go_access_network_type);
1345*a1157835SDaniel Fojt 	if (config->go_internet)
1346*a1157835SDaniel Fojt 		fprintf(f, "go_internet=%d\n", config->go_internet);
1347*a1157835SDaniel Fojt 	if (config->go_venue_group)
1348*a1157835SDaniel Fojt 		fprintf(f, "go_venue_group=%d\n", config->go_venue_group);
1349*a1157835SDaniel Fojt 	if (config->go_venue_type)
1350*a1157835SDaniel Fojt 		fprintf(f, "go_venue_type=%d\n", config->go_venue_type);
13513ff40c12SJohn Marino #endif /* CONFIG_INTERWORKING */
13523ff40c12SJohn Marino 	if (config->pbc_in_m1)
1353*a1157835SDaniel Fojt 		fprintf(f, "pbc_in_m1=%d\n", config->pbc_in_m1);
13543ff40c12SJohn Marino 	if (config->wps_nfc_pw_from_config) {
13553ff40c12SJohn Marino 		if (config->wps_nfc_dev_pw_id)
13563ff40c12SJohn Marino 			fprintf(f, "wps_nfc_dev_pw_id=%d\n",
13573ff40c12SJohn Marino 				config->wps_nfc_dev_pw_id);
13583ff40c12SJohn Marino 		write_global_bin(f, "wps_nfc_dh_pubkey",
13593ff40c12SJohn Marino 				 config->wps_nfc_dh_pubkey);
13603ff40c12SJohn Marino 		write_global_bin(f, "wps_nfc_dh_privkey",
13613ff40c12SJohn Marino 				 config->wps_nfc_dh_privkey);
13623ff40c12SJohn Marino 		write_global_bin(f, "wps_nfc_dev_pw", config->wps_nfc_dev_pw);
13633ff40c12SJohn Marino 	}
13643ff40c12SJohn Marino 
13653ff40c12SJohn Marino 	if (config->ext_password_backend)
13663ff40c12SJohn Marino 		fprintf(f, "ext_password_backend=%s\n",
13673ff40c12SJohn Marino 			config->ext_password_backend);
13683ff40c12SJohn Marino 	if (config->p2p_go_max_inactivity != DEFAULT_P2P_GO_MAX_INACTIVITY)
13693ff40c12SJohn Marino 		fprintf(f, "p2p_go_max_inactivity=%d\n",
13703ff40c12SJohn Marino 			config->p2p_go_max_inactivity);
13713ff40c12SJohn Marino 	if (config->auto_interworking)
13723ff40c12SJohn Marino 		fprintf(f, "auto_interworking=%d\n",
13733ff40c12SJohn Marino 			config->auto_interworking);
13743ff40c12SJohn Marino 	if (config->okc)
13753ff40c12SJohn Marino 		fprintf(f, "okc=%d\n", config->okc);
13763ff40c12SJohn Marino 	if (config->pmf)
13773ff40c12SJohn Marino 		fprintf(f, "pmf=%d\n", config->pmf);
13783ff40c12SJohn Marino 	if (config->dtim_period)
13793ff40c12SJohn Marino 		fprintf(f, "dtim_period=%d\n", config->dtim_period);
13803ff40c12SJohn Marino 	if (config->beacon_int)
13813ff40c12SJohn Marino 		fprintf(f, "beacon_int=%d\n", config->beacon_int);
13823ff40c12SJohn Marino 
13833ff40c12SJohn Marino 	if (config->sae_groups) {
13843ff40c12SJohn Marino 		int i;
13853ff40c12SJohn Marino 		fprintf(f, "sae_groups=");
1386*a1157835SDaniel Fojt 		for (i = 0; config->sae_groups[i] > 0; i++) {
13873ff40c12SJohn Marino 			fprintf(f, "%s%d", i > 0 ? " " : "",
13883ff40c12SJohn Marino 				config->sae_groups[i]);
13893ff40c12SJohn Marino 		}
13903ff40c12SJohn Marino 		fprintf(f, "\n");
13913ff40c12SJohn Marino 	}
13923ff40c12SJohn Marino 
13933ff40c12SJohn Marino 	if (config->ap_vendor_elements) {
13943ff40c12SJohn Marino 		int i, len = wpabuf_len(config->ap_vendor_elements);
13953ff40c12SJohn Marino 		const u8 *p = wpabuf_head_u8(config->ap_vendor_elements);
13963ff40c12SJohn Marino 		if (len > 0) {
13973ff40c12SJohn Marino 			fprintf(f, "ap_vendor_elements=");
13983ff40c12SJohn Marino 			for (i = 0; i < len; i++)
13993ff40c12SJohn Marino 				fprintf(f, "%02x", *p++);
14003ff40c12SJohn Marino 			fprintf(f, "\n");
14013ff40c12SJohn Marino 		}
14023ff40c12SJohn Marino 	}
14033ff40c12SJohn Marino 
14043ff40c12SJohn Marino 	if (config->ignore_old_scan_res)
14053ff40c12SJohn Marino 		fprintf(f, "ignore_old_scan_res=%d\n",
14063ff40c12SJohn Marino 			config->ignore_old_scan_res);
14073ff40c12SJohn Marino 
14083ff40c12SJohn Marino 	if (config->freq_list && config->freq_list[0]) {
14093ff40c12SJohn Marino 		int i;
14103ff40c12SJohn Marino 		fprintf(f, "freq_list=");
14113ff40c12SJohn Marino 		for (i = 0; config->freq_list[i]; i++) {
1412*a1157835SDaniel Fojt 			fprintf(f, "%s%d", i > 0 ? " " : "",
14133ff40c12SJohn Marino 				config->freq_list[i]);
14143ff40c12SJohn Marino 		}
14153ff40c12SJohn Marino 		fprintf(f, "\n");
14163ff40c12SJohn Marino 	}
14173ff40c12SJohn Marino 	if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ)
14183ff40c12SJohn Marino 		fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq);
14193ff40c12SJohn Marino 
14203ff40c12SJohn Marino 	if (config->sched_scan_interval)
14213ff40c12SJohn Marino 		fprintf(f, "sched_scan_interval=%u\n",
14223ff40c12SJohn Marino 			config->sched_scan_interval);
14233ff40c12SJohn Marino 
1424*a1157835SDaniel Fojt 	if (config->sched_scan_start_delay)
1425*a1157835SDaniel Fojt 		fprintf(f, "sched_scan_start_delay=%u\n",
1426*a1157835SDaniel Fojt 			config->sched_scan_start_delay);
1427*a1157835SDaniel Fojt 
14283ff40c12SJohn Marino 	if (config->external_sim)
14293ff40c12SJohn Marino 		fprintf(f, "external_sim=%d\n", config->external_sim);
14303ff40c12SJohn Marino 
14313ff40c12SJohn Marino 	if (config->tdls_external_control)
14323ff40c12SJohn Marino 		fprintf(f, "tdls_external_control=%d\n",
14333ff40c12SJohn Marino 			config->tdls_external_control);
1434*a1157835SDaniel Fojt 
1435*a1157835SDaniel Fojt 	if (config->wowlan_triggers)
1436*a1157835SDaniel Fojt 		fprintf(f, "wowlan_triggers=%s\n",
1437*a1157835SDaniel Fojt 			config->wowlan_triggers);
1438*a1157835SDaniel Fojt 
1439*a1157835SDaniel Fojt 	if (config->bgscan)
1440*a1157835SDaniel Fojt 		fprintf(f, "bgscan=\"%s\"\n", config->bgscan);
1441*a1157835SDaniel Fojt 
1442*a1157835SDaniel Fojt 	if (config->autoscan)
1443*a1157835SDaniel Fojt 		fprintf(f, "autoscan=%s\n", config->autoscan);
1444*a1157835SDaniel Fojt 
1445*a1157835SDaniel Fojt 	if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY)
1446*a1157835SDaniel Fojt 		fprintf(f, "p2p_search_delay=%u\n",
1447*a1157835SDaniel Fojt 			config->p2p_search_delay);
1448*a1157835SDaniel Fojt 
1449*a1157835SDaniel Fojt 	if (config->mac_addr)
1450*a1157835SDaniel Fojt 		fprintf(f, "mac_addr=%d\n", config->mac_addr);
1451*a1157835SDaniel Fojt 
1452*a1157835SDaniel Fojt 	if (config->rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME)
1453*a1157835SDaniel Fojt 		fprintf(f, "rand_addr_lifetime=%u\n",
1454*a1157835SDaniel Fojt 			config->rand_addr_lifetime);
1455*a1157835SDaniel Fojt 
1456*a1157835SDaniel Fojt 	if (config->preassoc_mac_addr)
1457*a1157835SDaniel Fojt 		fprintf(f, "preassoc_mac_addr=%d\n", config->preassoc_mac_addr);
1458*a1157835SDaniel Fojt 
1459*a1157835SDaniel Fojt 	if (config->key_mgmt_offload != DEFAULT_KEY_MGMT_OFFLOAD)
1460*a1157835SDaniel Fojt 		fprintf(f, "key_mgmt_offload=%d\n", config->key_mgmt_offload);
1461*a1157835SDaniel Fojt 
1462*a1157835SDaniel Fojt 	if (config->user_mpm != DEFAULT_USER_MPM)
1463*a1157835SDaniel Fojt 		fprintf(f, "user_mpm=%d\n", config->user_mpm);
1464*a1157835SDaniel Fojt 
1465*a1157835SDaniel Fojt 	if (config->max_peer_links != DEFAULT_MAX_PEER_LINKS)
1466*a1157835SDaniel Fojt 		fprintf(f, "max_peer_links=%d\n", config->max_peer_links);
1467*a1157835SDaniel Fojt 
1468*a1157835SDaniel Fojt 	if (config->cert_in_cb != DEFAULT_CERT_IN_CB)
1469*a1157835SDaniel Fojt 		fprintf(f, "cert_in_cb=%d\n", config->cert_in_cb);
1470*a1157835SDaniel Fojt 
1471*a1157835SDaniel Fojt 	if (config->mesh_max_inactivity != DEFAULT_MESH_MAX_INACTIVITY)
1472*a1157835SDaniel Fojt 		fprintf(f, "mesh_max_inactivity=%d\n",
1473*a1157835SDaniel Fojt 			config->mesh_max_inactivity);
1474*a1157835SDaniel Fojt 
1475*a1157835SDaniel Fojt 	if (config->dot11RSNASAERetransPeriod !=
1476*a1157835SDaniel Fojt 	    DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD)
1477*a1157835SDaniel Fojt 		fprintf(f, "dot11RSNASAERetransPeriod=%d\n",
1478*a1157835SDaniel Fojt 			config->dot11RSNASAERetransPeriod);
1479*a1157835SDaniel Fojt 
1480*a1157835SDaniel Fojt 	if (config->passive_scan)
1481*a1157835SDaniel Fojt 		fprintf(f, "passive_scan=%d\n", config->passive_scan);
1482*a1157835SDaniel Fojt 
1483*a1157835SDaniel Fojt 	if (config->reassoc_same_bss_optim)
1484*a1157835SDaniel Fojt 		fprintf(f, "reassoc_same_bss_optim=%d\n",
1485*a1157835SDaniel Fojt 			config->reassoc_same_bss_optim);
1486*a1157835SDaniel Fojt 
1487*a1157835SDaniel Fojt 	if (config->wps_priority)
1488*a1157835SDaniel Fojt 		fprintf(f, "wps_priority=%d\n", config->wps_priority);
1489*a1157835SDaniel Fojt 
1490*a1157835SDaniel Fojt 	if (config->wpa_rsc_relaxation != DEFAULT_WPA_RSC_RELAXATION)
1491*a1157835SDaniel Fojt 		fprintf(f, "wpa_rsc_relaxation=%d\n",
1492*a1157835SDaniel Fojt 			config->wpa_rsc_relaxation);
1493*a1157835SDaniel Fojt 
1494*a1157835SDaniel Fojt 	if (config->sched_scan_plans)
1495*a1157835SDaniel Fojt 		fprintf(f, "sched_scan_plans=%s\n", config->sched_scan_plans);
1496*a1157835SDaniel Fojt 
1497*a1157835SDaniel Fojt #ifdef CONFIG_MBO
1498*a1157835SDaniel Fojt 	if (config->non_pref_chan)
1499*a1157835SDaniel Fojt 		fprintf(f, "non_pref_chan=%s\n", config->non_pref_chan);
1500*a1157835SDaniel Fojt 	if (config->mbo_cell_capa != DEFAULT_MBO_CELL_CAPA)
1501*a1157835SDaniel Fojt 		fprintf(f, "mbo_cell_capa=%u\n", config->mbo_cell_capa);
1502*a1157835SDaniel Fojt 	if (config->disassoc_imminent_rssi_threshold !=
1503*a1157835SDaniel Fojt 	    DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD)
1504*a1157835SDaniel Fojt 		fprintf(f, "disassoc_imminent_rssi_threshold=%d\n",
1505*a1157835SDaniel Fojt 			config->disassoc_imminent_rssi_threshold);
1506*a1157835SDaniel Fojt 	if (config->oce != DEFAULT_OCE_SUPPORT)
1507*a1157835SDaniel Fojt 		fprintf(f, "oce=%u\n", config->oce);
1508*a1157835SDaniel Fojt #endif /* CONFIG_MBO */
1509*a1157835SDaniel Fojt 
1510*a1157835SDaniel Fojt 	if (config->gas_address3)
1511*a1157835SDaniel Fojt 		fprintf(f, "gas_address3=%d\n", config->gas_address3);
1512*a1157835SDaniel Fojt 
1513*a1157835SDaniel Fojt 	if (config->ftm_responder)
1514*a1157835SDaniel Fojt 		fprintf(f, "ftm_responder=%d\n", config->ftm_responder);
1515*a1157835SDaniel Fojt 	if (config->ftm_initiator)
1516*a1157835SDaniel Fojt 		fprintf(f, "ftm_initiator=%d\n", config->ftm_initiator);
1517*a1157835SDaniel Fojt 
1518*a1157835SDaniel Fojt 	if (config->osu_dir)
1519*a1157835SDaniel Fojt 		fprintf(f, "osu_dir=%s\n", config->osu_dir);
1520*a1157835SDaniel Fojt 
1521*a1157835SDaniel Fojt 	if (config->fst_group_id)
1522*a1157835SDaniel Fojt 		fprintf(f, "fst_group_id=%s\n", config->fst_group_id);
1523*a1157835SDaniel Fojt 	if (config->fst_priority)
1524*a1157835SDaniel Fojt 		fprintf(f, "fst_priority=%d\n", config->fst_priority);
1525*a1157835SDaniel Fojt 	if (config->fst_llt)
1526*a1157835SDaniel Fojt 		fprintf(f, "fst_llt=%d\n", config->fst_llt);
1527*a1157835SDaniel Fojt 
1528*a1157835SDaniel Fojt 	if (config->gas_rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME)
1529*a1157835SDaniel Fojt 		fprintf(f, "gas_rand_addr_lifetime=%u\n",
1530*a1157835SDaniel Fojt 			config->gas_rand_addr_lifetime);
1531*a1157835SDaniel Fojt 	if (config->gas_rand_mac_addr)
1532*a1157835SDaniel Fojt 		fprintf(f, "gas_rand_mac_addr=%d\n", config->gas_rand_mac_addr);
1533*a1157835SDaniel Fojt 	if (config->dpp_config_processing)
1534*a1157835SDaniel Fojt 		fprintf(f, "dpp_config_processing=%d\n",
1535*a1157835SDaniel Fojt 			config->dpp_config_processing);
1536*a1157835SDaniel Fojt 	if (config->coloc_intf_reporting)
1537*a1157835SDaniel Fojt 		fprintf(f, "coloc_intf_reporting=%d\n",
1538*a1157835SDaniel Fojt 			config->coloc_intf_reporting);
1539*a1157835SDaniel Fojt 	if (config->p2p_device_random_mac_addr)
1540*a1157835SDaniel Fojt 		fprintf(f, "p2p_device_random_mac_addr=%d\n",
1541*a1157835SDaniel Fojt 			config->p2p_device_random_mac_addr);
1542*a1157835SDaniel Fojt 	if (!is_zero_ether_addr(config->p2p_device_persistent_mac_addr))
1543*a1157835SDaniel Fojt 		fprintf(f, "p2p_device_persistent_mac_addr=" MACSTR "\n",
1544*a1157835SDaniel Fojt 			MAC2STR(config->p2p_device_persistent_mac_addr));
1545*a1157835SDaniel Fojt 	if (config->p2p_interface_random_mac_addr)
1546*a1157835SDaniel Fojt 		fprintf(f, "p2p_interface_random_mac_addr=%d\n",
1547*a1157835SDaniel Fojt 			config->p2p_interface_random_mac_addr);
1548*a1157835SDaniel Fojt 	if (config->disable_btm)
1549*a1157835SDaniel Fojt 		fprintf(f, "disable_btm=1\n");
15506d49e1aeSJan Lentfer }
15516d49e1aeSJan Lentfer 
15526d49e1aeSJan Lentfer #endif /* CONFIG_NO_CONFIG_WRITE */
15536d49e1aeSJan Lentfer 
15546d49e1aeSJan Lentfer 
wpa_config_write(const char * name,struct wpa_config * config)15556d49e1aeSJan Lentfer int wpa_config_write(const char *name, struct wpa_config *config)
15566d49e1aeSJan Lentfer {
15576d49e1aeSJan Lentfer #ifndef CONFIG_NO_CONFIG_WRITE
15586d49e1aeSJan Lentfer 	FILE *f;
15596d49e1aeSJan Lentfer 	struct wpa_ssid *ssid;
15603ff40c12SJohn Marino 	struct wpa_cred *cred;
15616d49e1aeSJan Lentfer #ifndef CONFIG_NO_CONFIG_BLOBS
15626d49e1aeSJan Lentfer 	struct wpa_config_blob *blob;
15636d49e1aeSJan Lentfer #endif /* CONFIG_NO_CONFIG_BLOBS */
15646d49e1aeSJan Lentfer 	int ret = 0;
1565*a1157835SDaniel Fojt 	const char *orig_name = name;
1566*a1157835SDaniel Fojt 	int tmp_len = os_strlen(name) + 5; /* allow space for .tmp suffix */
1567*a1157835SDaniel Fojt 	char *tmp_name = os_malloc(tmp_len);
1568*a1157835SDaniel Fojt 
1569*a1157835SDaniel Fojt 	if (tmp_name) {
1570*a1157835SDaniel Fojt 		os_snprintf(tmp_name, tmp_len, "%s.tmp", name);
1571*a1157835SDaniel Fojt 		name = tmp_name;
1572*a1157835SDaniel Fojt 	}
15736d49e1aeSJan Lentfer 
15746d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name);
15756d49e1aeSJan Lentfer 
15766d49e1aeSJan Lentfer 	f = fopen(name, "w");
15776d49e1aeSJan Lentfer 	if (f == NULL) {
15786d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name);
1579*a1157835SDaniel Fojt 		os_free(tmp_name);
15806d49e1aeSJan Lentfer 		return -1;
15816d49e1aeSJan Lentfer 	}
15826d49e1aeSJan Lentfer 
15836d49e1aeSJan Lentfer 	wpa_config_write_global(f, config);
15846d49e1aeSJan Lentfer 
15853ff40c12SJohn Marino 	for (cred = config->cred; cred; cred = cred->next) {
15863ff40c12SJohn Marino 		if (cred->temporary)
15873ff40c12SJohn Marino 			continue;
15883ff40c12SJohn Marino 		fprintf(f, "\ncred={\n");
15893ff40c12SJohn Marino 		wpa_config_write_cred(f, cred);
15903ff40c12SJohn Marino 		fprintf(f, "}\n");
15913ff40c12SJohn Marino 	}
15923ff40c12SJohn Marino 
15936d49e1aeSJan Lentfer 	for (ssid = config->ssid; ssid; ssid = ssid->next) {
15943ff40c12SJohn Marino 		if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary)
15953ff40c12SJohn Marino 			continue; /* do not save temporary networks */
15963ff40c12SJohn Marino 		if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
15973ff40c12SJohn Marino 		    !ssid->passphrase)
15983ff40c12SJohn Marino 			continue; /* do not save invalid network */
15996d49e1aeSJan Lentfer 		fprintf(f, "\nnetwork={\n");
16006d49e1aeSJan Lentfer 		wpa_config_write_network(f, ssid);
16016d49e1aeSJan Lentfer 		fprintf(f, "}\n");
16026d49e1aeSJan Lentfer 	}
16036d49e1aeSJan Lentfer 
16046d49e1aeSJan Lentfer #ifndef CONFIG_NO_CONFIG_BLOBS
16056d49e1aeSJan Lentfer 	for (blob = config->blobs; blob; blob = blob->next) {
16066d49e1aeSJan Lentfer 		ret = wpa_config_write_blob(f, blob);
16076d49e1aeSJan Lentfer 		if (ret)
16086d49e1aeSJan Lentfer 			break;
16096d49e1aeSJan Lentfer 	}
16106d49e1aeSJan Lentfer #endif /* CONFIG_NO_CONFIG_BLOBS */
16116d49e1aeSJan Lentfer 
1612*a1157835SDaniel Fojt 	os_fdatasync(f);
1613*a1157835SDaniel Fojt 
16146d49e1aeSJan Lentfer 	fclose(f);
16156d49e1aeSJan Lentfer 
1616*a1157835SDaniel Fojt 	if (tmp_name) {
1617*a1157835SDaniel Fojt 		int chmod_ret = 0;
1618*a1157835SDaniel Fojt 
1619*a1157835SDaniel Fojt #ifdef ANDROID
1620*a1157835SDaniel Fojt 		chmod_ret = chmod(tmp_name,
1621*a1157835SDaniel Fojt 				  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1622*a1157835SDaniel Fojt #endif /* ANDROID */
1623*a1157835SDaniel Fojt 		if (chmod_ret != 0 || rename(tmp_name, orig_name) != 0)
1624*a1157835SDaniel Fojt 			ret = -1;
1625*a1157835SDaniel Fojt 
1626*a1157835SDaniel Fojt 		os_free(tmp_name);
1627*a1157835SDaniel Fojt 	}
1628*a1157835SDaniel Fojt 
16296d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully",
1630*a1157835SDaniel Fojt 		   orig_name, ret ? "un" : "");
16316d49e1aeSJan Lentfer 	return ret;
16326d49e1aeSJan Lentfer #else /* CONFIG_NO_CONFIG_WRITE */
16336d49e1aeSJan Lentfer 	return -1;
16346d49e1aeSJan Lentfer #endif /* CONFIG_NO_CONFIG_WRITE */
16356d49e1aeSJan Lentfer }
1636