config_file.c revision 346981
1189251Ssam/* 2189251Ssam * WPA Supplicant / Configuration backend: text file 3252726Srpaulo * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam * 8189251Ssam * This file implements a configuration backend for text files. All the 9189251Ssam * configuration information is stored in a text file that uses a format 10189251Ssam * described in the sample configuration file, wpa_supplicant.conf. 11189251Ssam */ 12189251Ssam 13189251Ssam#include "includes.h" 14281806Srpaulo#ifdef ANDROID 15281806Srpaulo#include <sys/stat.h> 16281806Srpaulo#endif /* ANDROID */ 17189251Ssam 18189251Ssam#include "common.h" 19189251Ssam#include "config.h" 20189251Ssam#include "base64.h" 21189251Ssam#include "uuid.h" 22346981Scy#include "common/ieee802_1x_defs.h" 23252726Srpaulo#include "p2p/p2p.h" 24189251Ssam#include "eap_peer/eap_methods.h" 25252726Srpaulo#include "eap_peer/eap.h" 26189251Ssam 27189251Ssam 28252726Srpaulostatic int newline_terminated(const char *buf, size_t buflen) 29252726Srpaulo{ 30252726Srpaulo size_t len = os_strlen(buf); 31252726Srpaulo if (len == 0) 32252726Srpaulo return 0; 33252726Srpaulo if (len == buflen - 1 && buf[buflen - 1] != '\r' && 34252726Srpaulo buf[len - 1] != '\n') 35252726Srpaulo return 0; 36252726Srpaulo return 1; 37252726Srpaulo} 38252726Srpaulo 39252726Srpaulo 40252726Srpaulostatic void skip_line_end(FILE *stream) 41252726Srpaulo{ 42252726Srpaulo char buf[100]; 43252726Srpaulo while (fgets(buf, sizeof(buf), stream)) { 44252726Srpaulo buf[sizeof(buf) - 1] = '\0'; 45252726Srpaulo if (newline_terminated(buf, sizeof(buf))) 46252726Srpaulo return; 47252726Srpaulo } 48252726Srpaulo} 49252726Srpaulo 50252726Srpaulo 51189251Ssam/** 52189251Ssam * wpa_config_get_line - Read the next configuration file line 53189251Ssam * @s: Buffer for the line 54189251Ssam * @size: The buffer length 55189251Ssam * @stream: File stream to read from 56189251Ssam * @line: Pointer to a variable storing the file line number 57189251Ssam * @_pos: Buffer for the pointer to the beginning of data on the text line or 58189251Ssam * %NULL if not needed (returned value used instead) 59189251Ssam * Returns: Pointer to the beginning of data on the text line or %NULL if no 60189251Ssam * more text lines are available. 61189251Ssam * 62189251Ssam * This function reads the next non-empty line from the configuration file and 63189251Ssam * removes comments. The returned string is guaranteed to be null-terminated. 64189251Ssam */ 65189251Ssamstatic char * wpa_config_get_line(char *s, int size, FILE *stream, int *line, 66189251Ssam char **_pos) 67189251Ssam{ 68189251Ssam char *pos, *end, *sstart; 69189251Ssam 70189251Ssam while (fgets(s, size, stream)) { 71189251Ssam (*line)++; 72189251Ssam s[size - 1] = '\0'; 73252726Srpaulo if (!newline_terminated(s, size)) { 74252726Srpaulo /* 75252726Srpaulo * The line was truncated - skip rest of it to avoid 76252726Srpaulo * confusing error messages. 77252726Srpaulo */ 78252726Srpaulo wpa_printf(MSG_INFO, "Long line in configuration file " 79252726Srpaulo "truncated"); 80252726Srpaulo skip_line_end(stream); 81252726Srpaulo } 82189251Ssam pos = s; 83189251Ssam 84189251Ssam /* Skip white space from the beginning of line. */ 85189251Ssam while (*pos == ' ' || *pos == '\t' || *pos == '\r') 86189251Ssam pos++; 87189251Ssam 88189251Ssam /* Skip comment lines and empty lines */ 89189251Ssam if (*pos == '#' || *pos == '\n' || *pos == '\0') 90189251Ssam continue; 91189251Ssam 92189251Ssam /* 93189251Ssam * Remove # comments unless they are within a double quoted 94189251Ssam * string. 95189251Ssam */ 96189251Ssam sstart = os_strchr(pos, '"'); 97189251Ssam if (sstart) 98189251Ssam sstart = os_strrchr(sstart + 1, '"'); 99189251Ssam if (!sstart) 100189251Ssam sstart = pos; 101189251Ssam end = os_strchr(sstart, '#'); 102189251Ssam if (end) 103189251Ssam *end-- = '\0'; 104189251Ssam else 105189251Ssam end = pos + os_strlen(pos) - 1; 106189251Ssam 107189251Ssam /* Remove trailing white space. */ 108189251Ssam while (end > pos && 109189251Ssam (*end == '\n' || *end == ' ' || *end == '\t' || 110189251Ssam *end == '\r')) 111189251Ssam *end-- = '\0'; 112189251Ssam 113189251Ssam if (*pos == '\0') 114189251Ssam continue; 115189251Ssam 116189251Ssam if (_pos) 117189251Ssam *_pos = pos; 118189251Ssam return pos; 119189251Ssam } 120189251Ssam 121189251Ssam if (_pos) 122189251Ssam *_pos = NULL; 123189251Ssam return NULL; 124189251Ssam} 125189251Ssam 126189251Ssam 127189251Ssamstatic int wpa_config_validate_network(struct wpa_ssid *ssid, int line) 128189251Ssam{ 129189251Ssam int errors = 0; 130189251Ssam 131189251Ssam if (ssid->passphrase) { 132189251Ssam if (ssid->psk_set) { 133189251Ssam wpa_printf(MSG_ERROR, "Line %d: both PSK and " 134189251Ssam "passphrase configured.", line); 135189251Ssam errors++; 136189251Ssam } 137189251Ssam wpa_config_update_psk(ssid); 138189251Ssam } 139189251Ssam 140346981Scy if (ssid->disabled == 2) 141346981Scy ssid->p2p_persistent_group = 1; 142346981Scy 143189251Ssam if ((ssid->group_cipher & WPA_CIPHER_CCMP) && 144346981Scy !(ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 | 145346981Scy WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256 | 146346981Scy WPA_CIPHER_NONE))) { 147189251Ssam /* Group cipher cannot be stronger than the pairwise cipher. */ 148189251Ssam wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher" 149189251Ssam " list since it was not allowed for pairwise " 150189251Ssam "cipher", line); 151189251Ssam ssid->group_cipher &= ~WPA_CIPHER_CCMP; 152189251Ssam } 153189251Ssam 154281806Srpaulo if (ssid->mode == WPAS_MODE_MESH && 155281806Srpaulo (ssid->key_mgmt != WPA_KEY_MGMT_NONE && 156281806Srpaulo ssid->key_mgmt != WPA_KEY_MGMT_SAE)) { 157281806Srpaulo wpa_printf(MSG_ERROR, 158281806Srpaulo "Line %d: key_mgmt for mesh network should be open or SAE", 159281806Srpaulo line); 160281806Srpaulo errors++; 161281806Srpaulo } 162281806Srpaulo 163346981Scy#ifdef CONFIG_OCV 164346981Scy if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION) { 165346981Scy wpa_printf(MSG_ERROR, 166346981Scy "Line %d: PMF needs to be enabled whenever using OCV", 167346981Scy line); 168346981Scy errors++; 169346981Scy } 170346981Scy#endif /* CONFIG_OCV */ 171346981Scy 172189251Ssam return errors; 173189251Ssam} 174189251Ssam 175189251Ssam 176189251Ssamstatic struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) 177189251Ssam{ 178189251Ssam struct wpa_ssid *ssid; 179189251Ssam int errors = 0, end = 0; 180252726Srpaulo char buf[2000], *pos, *pos2; 181189251Ssam 182189251Ssam wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block", 183189251Ssam *line); 184189251Ssam ssid = os_zalloc(sizeof(*ssid)); 185189251Ssam if (ssid == NULL) 186189251Ssam return NULL; 187281806Srpaulo dl_list_init(&ssid->psk_list); 188189251Ssam ssid->id = id; 189189251Ssam 190189251Ssam wpa_config_set_network_defaults(ssid); 191189251Ssam 192189251Ssam while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 193189251Ssam if (os_strcmp(pos, "}") == 0) { 194189251Ssam end = 1; 195189251Ssam break; 196189251Ssam } 197189251Ssam 198189251Ssam pos2 = os_strchr(pos, '='); 199189251Ssam if (pos2 == NULL) { 200189251Ssam wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line " 201189251Ssam "'%s'.", *line, pos); 202189251Ssam errors++; 203189251Ssam continue; 204189251Ssam } 205189251Ssam 206189251Ssam *pos2++ = '\0'; 207189251Ssam if (*pos2 == '"') { 208189251Ssam if (os_strchr(pos2 + 1, '"') == NULL) { 209189251Ssam wpa_printf(MSG_ERROR, "Line %d: invalid " 210189251Ssam "quotation '%s'.", *line, pos2); 211189251Ssam errors++; 212189251Ssam continue; 213189251Ssam } 214189251Ssam } 215189251Ssam 216189251Ssam if (wpa_config_set(ssid, pos, pos2, *line) < 0) 217189251Ssam errors++; 218189251Ssam } 219189251Ssam 220189251Ssam if (!end) { 221189251Ssam wpa_printf(MSG_ERROR, "Line %d: network block was not " 222189251Ssam "terminated properly.", *line); 223189251Ssam errors++; 224189251Ssam } 225189251Ssam 226189251Ssam errors += wpa_config_validate_network(ssid, *line); 227189251Ssam 228189251Ssam if (errors) { 229189251Ssam wpa_config_free_ssid(ssid); 230189251Ssam ssid = NULL; 231189251Ssam } 232189251Ssam 233189251Ssam return ssid; 234189251Ssam} 235189251Ssam 236189251Ssam 237252726Srpaulostatic struct wpa_cred * wpa_config_read_cred(FILE *f, int *line, int id) 238252726Srpaulo{ 239252726Srpaulo struct wpa_cred *cred; 240252726Srpaulo int errors = 0, end = 0; 241252726Srpaulo char buf[256], *pos, *pos2; 242252726Srpaulo 243252726Srpaulo wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new cred block", *line); 244252726Srpaulo cred = os_zalloc(sizeof(*cred)); 245252726Srpaulo if (cred == NULL) 246252726Srpaulo return NULL; 247252726Srpaulo cred->id = id; 248281806Srpaulo cred->sim_num = DEFAULT_USER_SELECTED_SIM; 249252726Srpaulo 250252726Srpaulo while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 251252726Srpaulo if (os_strcmp(pos, "}") == 0) { 252252726Srpaulo end = 1; 253252726Srpaulo break; 254252726Srpaulo } 255252726Srpaulo 256252726Srpaulo pos2 = os_strchr(pos, '='); 257252726Srpaulo if (pos2 == NULL) { 258252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: Invalid cred line " 259252726Srpaulo "'%s'.", *line, pos); 260252726Srpaulo errors++; 261252726Srpaulo continue; 262252726Srpaulo } 263252726Srpaulo 264252726Srpaulo *pos2++ = '\0'; 265252726Srpaulo if (*pos2 == '"') { 266252726Srpaulo if (os_strchr(pos2 + 1, '"') == NULL) { 267252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: invalid " 268252726Srpaulo "quotation '%s'.", *line, pos2); 269252726Srpaulo errors++; 270252726Srpaulo continue; 271252726Srpaulo } 272252726Srpaulo } 273252726Srpaulo 274252726Srpaulo if (wpa_config_set_cred(cred, pos, pos2, *line) < 0) 275252726Srpaulo errors++; 276252726Srpaulo } 277252726Srpaulo 278252726Srpaulo if (!end) { 279252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: cred block was not " 280252726Srpaulo "terminated properly.", *line); 281252726Srpaulo errors++; 282252726Srpaulo } 283252726Srpaulo 284252726Srpaulo if (errors) { 285252726Srpaulo wpa_config_free_cred(cred); 286252726Srpaulo cred = NULL; 287252726Srpaulo } 288252726Srpaulo 289252726Srpaulo return cred; 290252726Srpaulo} 291252726Srpaulo 292252726Srpaulo 293189251Ssam#ifndef CONFIG_NO_CONFIG_BLOBS 294189251Ssamstatic struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line, 295189251Ssam const char *name) 296189251Ssam{ 297189251Ssam struct wpa_config_blob *blob; 298189251Ssam char buf[256], *pos; 299189251Ssam unsigned char *encoded = NULL, *nencoded; 300189251Ssam int end = 0; 301189251Ssam size_t encoded_len = 0, len; 302189251Ssam 303189251Ssam wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new named blob '%s'", 304189251Ssam *line, name); 305189251Ssam 306189251Ssam while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { 307189251Ssam if (os_strcmp(pos, "}") == 0) { 308189251Ssam end = 1; 309189251Ssam break; 310189251Ssam } 311189251Ssam 312189251Ssam len = os_strlen(pos); 313189251Ssam nencoded = os_realloc(encoded, encoded_len + len); 314189251Ssam if (nencoded == NULL) { 315189251Ssam wpa_printf(MSG_ERROR, "Line %d: not enough memory for " 316189251Ssam "blob", *line); 317189251Ssam os_free(encoded); 318189251Ssam return NULL; 319189251Ssam } 320189251Ssam encoded = nencoded; 321189251Ssam os_memcpy(encoded + encoded_len, pos, len); 322189251Ssam encoded_len += len; 323189251Ssam } 324189251Ssam 325346981Scy if (!end || !encoded) { 326189251Ssam wpa_printf(MSG_ERROR, "Line %d: blob was not terminated " 327189251Ssam "properly", *line); 328189251Ssam os_free(encoded); 329189251Ssam return NULL; 330189251Ssam } 331189251Ssam 332189251Ssam blob = os_zalloc(sizeof(*blob)); 333189251Ssam if (blob == NULL) { 334189251Ssam os_free(encoded); 335189251Ssam return NULL; 336189251Ssam } 337189251Ssam blob->name = os_strdup(name); 338189251Ssam blob->data = base64_decode(encoded, encoded_len, &blob->len); 339189251Ssam os_free(encoded); 340189251Ssam 341189251Ssam if (blob->name == NULL || blob->data == NULL) { 342189251Ssam wpa_config_free_blob(blob); 343189251Ssam return NULL; 344189251Ssam } 345189251Ssam 346189251Ssam return blob; 347189251Ssam} 348189251Ssam 349189251Ssam 350189251Ssamstatic int wpa_config_process_blob(struct wpa_config *config, FILE *f, 351189251Ssam int *line, char *bname) 352189251Ssam{ 353189251Ssam char *name_end; 354189251Ssam struct wpa_config_blob *blob; 355189251Ssam 356189251Ssam name_end = os_strchr(bname, '='); 357189251Ssam if (name_end == NULL) { 358189251Ssam wpa_printf(MSG_ERROR, "Line %d: no blob name terminator", 359189251Ssam *line); 360189251Ssam return -1; 361189251Ssam } 362189251Ssam *name_end = '\0'; 363189251Ssam 364189251Ssam blob = wpa_config_read_blob(f, line, bname); 365189251Ssam if (blob == NULL) { 366189251Ssam wpa_printf(MSG_ERROR, "Line %d: failed to read blob %s", 367189251Ssam *line, bname); 368189251Ssam return -1; 369189251Ssam } 370189251Ssam wpa_config_set_blob(config, blob); 371189251Ssam return 0; 372189251Ssam} 373189251Ssam#endif /* CONFIG_NO_CONFIG_BLOBS */ 374189251Ssam 375189251Ssam 376281806Srpaulostruct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp) 377189251Ssam{ 378189251Ssam FILE *f; 379252726Srpaulo char buf[512], *pos; 380189251Ssam int errors = 0, line = 0; 381281806Srpaulo struct wpa_ssid *ssid, *tail, *head; 382281806Srpaulo struct wpa_cred *cred, *cred_tail, *cred_head; 383189251Ssam struct wpa_config *config; 384189251Ssam int id = 0; 385252726Srpaulo int cred_id = 0; 386189251Ssam 387281806Srpaulo if (name == NULL) 388281806Srpaulo return NULL; 389281806Srpaulo if (cfgp) 390281806Srpaulo config = cfgp; 391281806Srpaulo else 392281806Srpaulo config = wpa_config_alloc_empty(NULL, NULL); 393252726Srpaulo if (config == NULL) { 394252726Srpaulo wpa_printf(MSG_ERROR, "Failed to allocate config file " 395252726Srpaulo "structure"); 396189251Ssam return NULL; 397252726Srpaulo } 398281806Srpaulo tail = head = config->ssid; 399281806Srpaulo while (tail && tail->next) 400281806Srpaulo tail = tail->next; 401281806Srpaulo cred_tail = cred_head = config->cred; 402281806Srpaulo while (cred_tail && cred_tail->next) 403281806Srpaulo cred_tail = cred_tail->next; 404252726Srpaulo 405189251Ssam wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); 406189251Ssam f = fopen(name, "r"); 407189251Ssam if (f == NULL) { 408252726Srpaulo wpa_printf(MSG_ERROR, "Failed to open config file '%s', " 409252726Srpaulo "error: %s", name, strerror(errno)); 410346981Scy if (config != cfgp) 411346981Scy os_free(config); 412189251Ssam return NULL; 413189251Ssam } 414189251Ssam 415189251Ssam while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { 416189251Ssam if (os_strcmp(pos, "network={") == 0) { 417189251Ssam ssid = wpa_config_read_network(f, &line, id++); 418189251Ssam if (ssid == NULL) { 419189251Ssam wpa_printf(MSG_ERROR, "Line %d: failed to " 420189251Ssam "parse network block.", line); 421189251Ssam errors++; 422189251Ssam continue; 423189251Ssam } 424189251Ssam if (head == NULL) { 425189251Ssam head = tail = ssid; 426189251Ssam } else { 427189251Ssam tail->next = ssid; 428189251Ssam tail = ssid; 429189251Ssam } 430189251Ssam if (wpa_config_add_prio_network(config, ssid)) { 431189251Ssam wpa_printf(MSG_ERROR, "Line %d: failed to add " 432189251Ssam "network block to priority list.", 433189251Ssam line); 434189251Ssam errors++; 435189251Ssam continue; 436189251Ssam } 437252726Srpaulo } else if (os_strcmp(pos, "cred={") == 0) { 438252726Srpaulo cred = wpa_config_read_cred(f, &line, cred_id++); 439252726Srpaulo if (cred == NULL) { 440252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: failed to " 441252726Srpaulo "parse cred block.", line); 442252726Srpaulo errors++; 443252726Srpaulo continue; 444252726Srpaulo } 445252726Srpaulo if (cred_head == NULL) { 446252726Srpaulo cred_head = cred_tail = cred; 447252726Srpaulo } else { 448252726Srpaulo cred_tail->next = cred; 449252726Srpaulo cred_tail = cred; 450252726Srpaulo } 451189251Ssam#ifndef CONFIG_NO_CONFIG_BLOBS 452189251Ssam } else if (os_strncmp(pos, "blob-base64-", 12) == 0) { 453189251Ssam if (wpa_config_process_blob(config, f, &line, pos + 12) 454189251Ssam < 0) { 455252726Srpaulo wpa_printf(MSG_ERROR, "Line %d: failed to " 456252726Srpaulo "process blob.", line); 457189251Ssam errors++; 458189251Ssam continue; 459189251Ssam } 460189251Ssam#endif /* CONFIG_NO_CONFIG_BLOBS */ 461189251Ssam } else if (wpa_config_process_global(config, pos, line) < 0) { 462189251Ssam wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " 463189251Ssam "line '%s'.", line, pos); 464189251Ssam errors++; 465189251Ssam continue; 466189251Ssam } 467189251Ssam } 468189251Ssam 469189251Ssam fclose(f); 470189251Ssam 471189251Ssam config->ssid = head; 472189251Ssam wpa_config_debug_dump_networks(config); 473252726Srpaulo config->cred = cred_head; 474189251Ssam 475252726Srpaulo#ifndef WPA_IGNORE_CONFIG_ERRORS 476189251Ssam if (errors) { 477346981Scy if (config != cfgp) 478346981Scy wpa_config_free(config); 479189251Ssam config = NULL; 480189251Ssam head = NULL; 481189251Ssam } 482252726Srpaulo#endif /* WPA_IGNORE_CONFIG_ERRORS */ 483189251Ssam 484189251Ssam return config; 485189251Ssam} 486189251Ssam 487189251Ssam 488189251Ssam#ifndef CONFIG_NO_CONFIG_WRITE 489189251Ssam 490189251Ssamstatic void write_str(FILE *f, const char *field, struct wpa_ssid *ssid) 491189251Ssam{ 492189251Ssam char *value = wpa_config_get(ssid, field); 493189251Ssam if (value == NULL) 494189251Ssam return; 495189251Ssam fprintf(f, "\t%s=%s\n", field, value); 496346981Scy str_clear_free(value); 497189251Ssam} 498189251Ssam 499189251Ssam 500189251Ssamstatic void write_int(FILE *f, const char *field, int value, int def) 501189251Ssam{ 502189251Ssam if (value == def) 503189251Ssam return; 504189251Ssam fprintf(f, "\t%s=%d\n", field, value); 505189251Ssam} 506189251Ssam 507189251Ssam 508189251Ssamstatic void write_bssid(FILE *f, struct wpa_ssid *ssid) 509189251Ssam{ 510189251Ssam char *value = wpa_config_get(ssid, "bssid"); 511189251Ssam if (value == NULL) 512189251Ssam return; 513189251Ssam fprintf(f, "\tbssid=%s\n", value); 514189251Ssam os_free(value); 515189251Ssam} 516189251Ssam 517189251Ssam 518346981Scystatic void write_bssid_hint(FILE *f, struct wpa_ssid *ssid) 519346981Scy{ 520346981Scy char *value = wpa_config_get(ssid, "bssid_hint"); 521346981Scy 522346981Scy if (!value) 523346981Scy return; 524346981Scy fprintf(f, "\tbssid_hint=%s\n", value); 525346981Scy os_free(value); 526346981Scy} 527346981Scy 528346981Scy 529189251Ssamstatic void write_psk(FILE *f, struct wpa_ssid *ssid) 530189251Ssam{ 531289549Srpaulo char *value; 532289549Srpaulo 533289549Srpaulo if (ssid->mem_only_psk) 534289549Srpaulo return; 535289549Srpaulo 536289549Srpaulo value = wpa_config_get(ssid, "psk"); 537189251Ssam if (value == NULL) 538189251Ssam return; 539189251Ssam fprintf(f, "\tpsk=%s\n", value); 540189251Ssam os_free(value); 541189251Ssam} 542189251Ssam 543189251Ssam 544189251Ssamstatic void write_proto(FILE *f, struct wpa_ssid *ssid) 545189251Ssam{ 546189251Ssam char *value; 547189251Ssam 548189251Ssam if (ssid->proto == DEFAULT_PROTO) 549189251Ssam return; 550189251Ssam 551189251Ssam value = wpa_config_get(ssid, "proto"); 552189251Ssam if (value == NULL) 553189251Ssam return; 554189251Ssam if (value[0]) 555189251Ssam fprintf(f, "\tproto=%s\n", value); 556189251Ssam os_free(value); 557189251Ssam} 558189251Ssam 559189251Ssam 560189251Ssamstatic void write_key_mgmt(FILE *f, struct wpa_ssid *ssid) 561189251Ssam{ 562189251Ssam char *value; 563189251Ssam 564189251Ssam if (ssid->key_mgmt == DEFAULT_KEY_MGMT) 565189251Ssam return; 566189251Ssam 567189251Ssam value = wpa_config_get(ssid, "key_mgmt"); 568189251Ssam if (value == NULL) 569189251Ssam return; 570189251Ssam if (value[0]) 571189251Ssam fprintf(f, "\tkey_mgmt=%s\n", value); 572189251Ssam os_free(value); 573189251Ssam} 574189251Ssam 575189251Ssam 576189251Ssamstatic void write_pairwise(FILE *f, struct wpa_ssid *ssid) 577189251Ssam{ 578189251Ssam char *value; 579189251Ssam 580189251Ssam if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) 581189251Ssam return; 582189251Ssam 583189251Ssam value = wpa_config_get(ssid, "pairwise"); 584189251Ssam if (value == NULL) 585189251Ssam return; 586189251Ssam if (value[0]) 587189251Ssam fprintf(f, "\tpairwise=%s\n", value); 588189251Ssam os_free(value); 589189251Ssam} 590189251Ssam 591189251Ssam 592189251Ssamstatic void write_group(FILE *f, struct wpa_ssid *ssid) 593189251Ssam{ 594189251Ssam char *value; 595189251Ssam 596189251Ssam if (ssid->group_cipher == DEFAULT_GROUP) 597189251Ssam return; 598189251Ssam 599189251Ssam value = wpa_config_get(ssid, "group"); 600189251Ssam if (value == NULL) 601189251Ssam return; 602189251Ssam if (value[0]) 603189251Ssam fprintf(f, "\tgroup=%s\n", value); 604189251Ssam os_free(value); 605189251Ssam} 606189251Ssam 607189251Ssam 608346981Scystatic void write_group_mgmt(FILE *f, struct wpa_ssid *ssid) 609346981Scy{ 610346981Scy char *value; 611346981Scy 612346981Scy if (!ssid->group_mgmt_cipher) 613346981Scy return; 614346981Scy 615346981Scy value = wpa_config_get(ssid, "group_mgmt"); 616346981Scy if (!value) 617346981Scy return; 618346981Scy if (value[0]) 619346981Scy fprintf(f, "\tgroup_mgmt=%s\n", value); 620346981Scy os_free(value); 621346981Scy} 622346981Scy 623346981Scy 624189251Ssamstatic void write_auth_alg(FILE *f, struct wpa_ssid *ssid) 625189251Ssam{ 626189251Ssam char *value; 627189251Ssam 628189251Ssam if (ssid->auth_alg == 0) 629189251Ssam return; 630189251Ssam 631189251Ssam value = wpa_config_get(ssid, "auth_alg"); 632189251Ssam if (value == NULL) 633189251Ssam return; 634189251Ssam if (value[0]) 635189251Ssam fprintf(f, "\tauth_alg=%s\n", value); 636189251Ssam os_free(value); 637189251Ssam} 638189251Ssam 639189251Ssam 640189251Ssam#ifdef IEEE8021X_EAPOL 641189251Ssamstatic void write_eap(FILE *f, struct wpa_ssid *ssid) 642189251Ssam{ 643189251Ssam char *value; 644189251Ssam 645189251Ssam value = wpa_config_get(ssid, "eap"); 646189251Ssam if (value == NULL) 647189251Ssam return; 648189251Ssam 649189251Ssam if (value[0]) 650189251Ssam fprintf(f, "\teap=%s\n", value); 651189251Ssam os_free(value); 652189251Ssam} 653189251Ssam#endif /* IEEE8021X_EAPOL */ 654189251Ssam 655189251Ssam 656189251Ssamstatic void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) 657189251Ssam{ 658189251Ssam char field[20], *value; 659189251Ssam int res; 660189251Ssam 661189251Ssam res = os_snprintf(field, sizeof(field), "wep_key%d", idx); 662281806Srpaulo if (os_snprintf_error(sizeof(field), res)) 663189251Ssam return; 664189251Ssam value = wpa_config_get(ssid, field); 665189251Ssam if (value) { 666189251Ssam fprintf(f, "\t%s=%s\n", field, value); 667189251Ssam os_free(value); 668189251Ssam } 669189251Ssam} 670189251Ssam 671189251Ssam 672252726Srpaulo#ifdef CONFIG_P2P 673281806Srpaulo 674281806Srpaulostatic void write_go_p2p_dev_addr(FILE *f, struct wpa_ssid *ssid) 675281806Srpaulo{ 676281806Srpaulo char *value = wpa_config_get(ssid, "go_p2p_dev_addr"); 677281806Srpaulo if (value == NULL) 678281806Srpaulo return; 679281806Srpaulo fprintf(f, "\tgo_p2p_dev_addr=%s\n", value); 680281806Srpaulo os_free(value); 681281806Srpaulo} 682281806Srpaulo 683252726Srpaulostatic void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid) 684252726Srpaulo{ 685252726Srpaulo char *value = wpa_config_get(ssid, "p2p_client_list"); 686252726Srpaulo if (value == NULL) 687252726Srpaulo return; 688252726Srpaulo fprintf(f, "\tp2p_client_list=%s\n", value); 689252726Srpaulo os_free(value); 690252726Srpaulo} 691281806Srpaulo 692281806Srpaulo 693281806Srpaulostatic void write_psk_list(FILE *f, struct wpa_ssid *ssid) 694281806Srpaulo{ 695281806Srpaulo struct psk_list_entry *psk; 696281806Srpaulo char hex[32 * 2 + 1]; 697281806Srpaulo 698281806Srpaulo dl_list_for_each(psk, &ssid->psk_list, struct psk_list_entry, list) { 699281806Srpaulo wpa_snprintf_hex(hex, sizeof(hex), psk->psk, sizeof(psk->psk)); 700281806Srpaulo fprintf(f, "\tpsk_list=%s" MACSTR "-%s\n", 701281806Srpaulo psk->p2p ? "P2P-" : "", MAC2STR(psk->addr), hex); 702281806Srpaulo } 703281806Srpaulo} 704281806Srpaulo 705252726Srpaulo#endif /* CONFIG_P2P */ 706252726Srpaulo 707252726Srpaulo 708346981Scy#ifdef CONFIG_MACSEC 709346981Scy 710346981Scystatic void write_mka_cak(FILE *f, struct wpa_ssid *ssid) 711346981Scy{ 712346981Scy char *value; 713346981Scy 714346981Scy if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK)) 715346981Scy return; 716346981Scy 717346981Scy value = wpa_config_get(ssid, "mka_cak"); 718346981Scy if (!value) 719346981Scy return; 720346981Scy fprintf(f, "\tmka_cak=%s\n", value); 721346981Scy os_free(value); 722346981Scy} 723346981Scy 724346981Scy 725346981Scystatic void write_mka_ckn(FILE *f, struct wpa_ssid *ssid) 726346981Scy{ 727346981Scy char *value; 728346981Scy 729346981Scy if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN)) 730346981Scy return; 731346981Scy 732346981Scy value = wpa_config_get(ssid, "mka_ckn"); 733346981Scy if (!value) 734346981Scy return; 735346981Scy fprintf(f, "\tmka_ckn=%s\n", value); 736346981Scy os_free(value); 737346981Scy} 738346981Scy 739346981Scy#endif /* CONFIG_MACSEC */ 740346981Scy 741346981Scy 742189251Ssamstatic void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) 743189251Ssam{ 744189251Ssam int i; 745189251Ssam 746189251Ssam#define STR(t) write_str(f, #t, ssid) 747189251Ssam#define INT(t) write_int(f, #t, ssid->t, 0) 748189251Ssam#define INTe(t) write_int(f, #t, ssid->eap.t, 0) 749189251Ssam#define INT_DEF(t, def) write_int(f, #t, ssid->t, def) 750189251Ssam#define INT_DEFe(t, def) write_int(f, #t, ssid->eap.t, def) 751189251Ssam 752189251Ssam STR(ssid); 753189251Ssam INT(scan_ssid); 754189251Ssam write_bssid(f, ssid); 755346981Scy write_bssid_hint(f, ssid); 756281806Srpaulo write_str(f, "bssid_blacklist", ssid); 757281806Srpaulo write_str(f, "bssid_whitelist", ssid); 758189251Ssam write_psk(f, ssid); 759289549Srpaulo INT(mem_only_psk); 760346981Scy STR(sae_password); 761346981Scy STR(sae_password_id); 762189251Ssam write_proto(f, ssid); 763189251Ssam write_key_mgmt(f, ssid); 764252726Srpaulo INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD); 765189251Ssam write_pairwise(f, ssid); 766189251Ssam write_group(f, ssid); 767346981Scy write_group_mgmt(f, ssid); 768189251Ssam write_auth_alg(f, ssid); 769252726Srpaulo STR(bgscan); 770252726Srpaulo STR(autoscan); 771281806Srpaulo STR(scan_freq); 772189251Ssam#ifdef IEEE8021X_EAPOL 773189251Ssam write_eap(f, ssid); 774189251Ssam STR(identity); 775189251Ssam STR(anonymous_identity); 776346981Scy STR(imsi_identity); 777189251Ssam STR(password); 778189251Ssam STR(ca_cert); 779189251Ssam STR(ca_path); 780189251Ssam STR(client_cert); 781189251Ssam STR(private_key); 782189251Ssam STR(private_key_passwd); 783189251Ssam STR(dh_file); 784189251Ssam STR(subject_match); 785346981Scy STR(check_cert_subject); 786189251Ssam STR(altsubject_match); 787281806Srpaulo STR(domain_suffix_match); 788281806Srpaulo STR(domain_match); 789189251Ssam STR(ca_cert2); 790189251Ssam STR(ca_path2); 791189251Ssam STR(client_cert2); 792189251Ssam STR(private_key2); 793189251Ssam STR(private_key2_passwd); 794189251Ssam STR(dh_file2); 795189251Ssam STR(subject_match2); 796346981Scy STR(check_cert_subject2); 797189251Ssam STR(altsubject_match2); 798281806Srpaulo STR(domain_suffix_match2); 799281806Srpaulo STR(domain_match2); 800189251Ssam STR(phase1); 801189251Ssam STR(phase2); 802189251Ssam STR(pcsc); 803189251Ssam STR(pin); 804189251Ssam STR(engine_id); 805189251Ssam STR(key_id); 806189251Ssam STR(cert_id); 807189251Ssam STR(ca_cert_id); 808189251Ssam STR(key2_id); 809189251Ssam STR(pin2); 810189251Ssam STR(engine2_id); 811189251Ssam STR(cert2_id); 812189251Ssam STR(ca_cert2_id); 813189251Ssam INTe(engine); 814189251Ssam INTe(engine2); 815189251Ssam INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); 816281806Srpaulo STR(openssl_ciphers); 817281806Srpaulo INTe(erp); 818189251Ssam#endif /* IEEE8021X_EAPOL */ 819189251Ssam for (i = 0; i < 4; i++) 820189251Ssam write_wep_key(f, i, ssid); 821189251Ssam INT(wep_tx_keyidx); 822189251Ssam INT(priority); 823189251Ssam#ifdef IEEE8021X_EAPOL 824189251Ssam INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); 825189251Ssam STR(pac_file); 826189251Ssam INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE); 827281806Srpaulo INTe(ocsp); 828281806Srpaulo INT_DEFe(sim_num, DEFAULT_USER_SELECTED_SIM); 829189251Ssam#endif /* IEEE8021X_EAPOL */ 830189251Ssam INT(mode); 831281806Srpaulo INT(no_auto_peer); 832252726Srpaulo INT(frequency); 833281806Srpaulo INT(fixed_freq); 834337817Scy#ifdef CONFIG_ACS 835337817Scy INT(acs); 836337817Scy#endif /* CONFIG_ACS */ 837252726Srpaulo write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1); 838189251Ssam INT(disabled); 839281806Srpaulo INT(mixed_cell); 840346981Scy INT(vht); 841346981Scy INT_DEF(ht, 1); 842346981Scy INT(ht40); 843346981Scy INT_DEF(max_oper_chwidth, DEFAULT_MAX_OPER_CHWIDTH); 844346981Scy INT(vht_center_freq1); 845346981Scy INT(vht_center_freq2); 846337817Scy INT(pbss); 847337817Scy INT(wps_disabled); 848346981Scy INT(fils_dh_group); 849189251Ssam#ifdef CONFIG_IEEE80211W 850252726Srpaulo write_int(f, "ieee80211w", ssid->ieee80211w, 851252726Srpaulo MGMT_FRAME_PROTECTION_DEFAULT); 852189251Ssam#endif /* CONFIG_IEEE80211W */ 853189251Ssam STR(id_str); 854252726Srpaulo#ifdef CONFIG_P2P 855281806Srpaulo write_go_p2p_dev_addr(f, ssid); 856252726Srpaulo write_p2p_client_list(f, ssid); 857281806Srpaulo write_psk_list(f, ssid); 858252726Srpaulo#endif /* CONFIG_P2P */ 859281806Srpaulo INT(ap_max_inactivity); 860281806Srpaulo INT(dtim_period); 861281806Srpaulo INT(beacon_int); 862281806Srpaulo#ifdef CONFIG_MACSEC 863281806Srpaulo INT(macsec_policy); 864346981Scy write_mka_cak(f, ssid); 865346981Scy write_mka_ckn(f, ssid); 866346981Scy INT(macsec_integ_only); 867346981Scy INT(macsec_replay_protect); 868346981Scy INT(macsec_replay_window); 869346981Scy INT(macsec_port); 870346981Scy INT_DEF(mka_priority, DEFAULT_PRIO_NOT_KEY_SERVER); 871281806Srpaulo#endif /* CONFIG_MACSEC */ 872281806Srpaulo#ifdef CONFIG_HS20 873281806Srpaulo INT(update_identifier); 874346981Scy STR(roaming_consortium_selection); 875281806Srpaulo#endif /* CONFIG_HS20 */ 876281806Srpaulo write_int(f, "mac_addr", ssid->mac_addr, -1); 877281806Srpaulo#ifdef CONFIG_MESH 878281806Srpaulo STR(mesh_basic_rates); 879281806Srpaulo INT_DEF(dot11MeshMaxRetries, DEFAULT_MESH_MAX_RETRIES); 880281806Srpaulo INT_DEF(dot11MeshRetryTimeout, DEFAULT_MESH_RETRY_TIMEOUT); 881281806Srpaulo INT_DEF(dot11MeshConfirmTimeout, DEFAULT_MESH_CONFIRM_TIMEOUT); 882281806Srpaulo INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT); 883346981Scy INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD); 884281806Srpaulo#endif /* CONFIG_MESH */ 885281806Srpaulo INT(wpa_ptk_rekey); 886337817Scy INT(group_rekey); 887281806Srpaulo INT(ignore_broadcast_ssid); 888346981Scy#ifdef CONFIG_DPP 889346981Scy STR(dpp_connector); 890346981Scy STR(dpp_netaccesskey); 891346981Scy INT(dpp_netaccesskey_expiry); 892346981Scy STR(dpp_csign); 893346981Scy#endif /* CONFIG_DPP */ 894346981Scy INT(owe_group); 895346981Scy INT(owe_only); 896346981Scy INT(multi_ap_backhaul_sta); 897281806Srpaulo#ifdef CONFIG_HT_OVERRIDES 898281806Srpaulo INT_DEF(disable_ht, DEFAULT_DISABLE_HT); 899281806Srpaulo INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40); 900281806Srpaulo INT_DEF(disable_sgi, DEFAULT_DISABLE_SGI); 901281806Srpaulo INT_DEF(disable_ldpc, DEFAULT_DISABLE_LDPC); 902281806Srpaulo INT(ht40_intolerant); 903346981Scy INT_DEF(tx_stbc, DEFAULT_TX_STBC); 904346981Scy INT_DEF(rx_stbc, DEFAULT_RX_STBC); 905281806Srpaulo INT_DEF(disable_max_amsdu, DEFAULT_DISABLE_MAX_AMSDU); 906281806Srpaulo INT_DEF(ampdu_factor, DEFAULT_AMPDU_FACTOR); 907281806Srpaulo INT_DEF(ampdu_density, DEFAULT_AMPDU_DENSITY); 908281806Srpaulo STR(ht_mcs); 909281806Srpaulo#endif /* CONFIG_HT_OVERRIDES */ 910281806Srpaulo#ifdef CONFIG_VHT_OVERRIDES 911281806Srpaulo INT(disable_vht); 912281806Srpaulo INT(vht_capa); 913281806Srpaulo INT(vht_capa_mask); 914281806Srpaulo INT_DEF(vht_rx_mcs_nss_1, -1); 915281806Srpaulo INT_DEF(vht_rx_mcs_nss_2, -1); 916281806Srpaulo INT_DEF(vht_rx_mcs_nss_3, -1); 917281806Srpaulo INT_DEF(vht_rx_mcs_nss_4, -1); 918281806Srpaulo INT_DEF(vht_rx_mcs_nss_5, -1); 919281806Srpaulo INT_DEF(vht_rx_mcs_nss_6, -1); 920281806Srpaulo INT_DEF(vht_rx_mcs_nss_7, -1); 921281806Srpaulo INT_DEF(vht_rx_mcs_nss_8, -1); 922281806Srpaulo INT_DEF(vht_tx_mcs_nss_1, -1); 923281806Srpaulo INT_DEF(vht_tx_mcs_nss_2, -1); 924281806Srpaulo INT_DEF(vht_tx_mcs_nss_3, -1); 925281806Srpaulo INT_DEF(vht_tx_mcs_nss_4, -1); 926281806Srpaulo INT_DEF(vht_tx_mcs_nss_5, -1); 927281806Srpaulo INT_DEF(vht_tx_mcs_nss_6, -1); 928281806Srpaulo INT_DEF(vht_tx_mcs_nss_7, -1); 929281806Srpaulo INT_DEF(vht_tx_mcs_nss_8, -1); 930281806Srpaulo#endif /* CONFIG_VHT_OVERRIDES */ 931189251Ssam 932189251Ssam#undef STR 933189251Ssam#undef INT 934189251Ssam#undef INT_DEF 935189251Ssam} 936189251Ssam 937189251Ssam 938252726Srpaulostatic void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) 939252726Srpaulo{ 940281806Srpaulo size_t i; 941281806Srpaulo 942252726Srpaulo if (cred->priority) 943252726Srpaulo fprintf(f, "\tpriority=%d\n", cred->priority); 944252726Srpaulo if (cred->pcsc) 945252726Srpaulo fprintf(f, "\tpcsc=%d\n", cred->pcsc); 946252726Srpaulo if (cred->realm) 947252726Srpaulo fprintf(f, "\trealm=\"%s\"\n", cred->realm); 948252726Srpaulo if (cred->username) 949252726Srpaulo fprintf(f, "\tusername=\"%s\"\n", cred->username); 950252726Srpaulo if (cred->password && cred->ext_password) 951252726Srpaulo fprintf(f, "\tpassword=ext:%s\n", cred->password); 952252726Srpaulo else if (cred->password) 953252726Srpaulo fprintf(f, "\tpassword=\"%s\"\n", cred->password); 954252726Srpaulo if (cred->ca_cert) 955252726Srpaulo fprintf(f, "\tca_cert=\"%s\"\n", cred->ca_cert); 956252726Srpaulo if (cred->client_cert) 957252726Srpaulo fprintf(f, "\tclient_cert=\"%s\"\n", cred->client_cert); 958252726Srpaulo if (cred->private_key) 959252726Srpaulo fprintf(f, "\tprivate_key=\"%s\"\n", cred->private_key); 960252726Srpaulo if (cred->private_key_passwd) 961252726Srpaulo fprintf(f, "\tprivate_key_passwd=\"%s\"\n", 962252726Srpaulo cred->private_key_passwd); 963252726Srpaulo if (cred->imsi) 964252726Srpaulo fprintf(f, "\timsi=\"%s\"\n", cred->imsi); 965252726Srpaulo if (cred->milenage) 966252726Srpaulo fprintf(f, "\tmilenage=\"%s\"\n", cred->milenage); 967281806Srpaulo for (i = 0; i < cred->num_domain; i++) 968281806Srpaulo fprintf(f, "\tdomain=\"%s\"\n", cred->domain[i]); 969281806Srpaulo if (cred->domain_suffix_match) 970281806Srpaulo fprintf(f, "\tdomain_suffix_match=\"%s\"\n", 971281806Srpaulo cred->domain_suffix_match); 972252726Srpaulo if (cred->roaming_consortium_len) { 973252726Srpaulo fprintf(f, "\troaming_consortium="); 974252726Srpaulo for (i = 0; i < cred->roaming_consortium_len; i++) 975252726Srpaulo fprintf(f, "%02x", cred->roaming_consortium[i]); 976252726Srpaulo fprintf(f, "\n"); 977252726Srpaulo } 978252726Srpaulo if (cred->eap_method) { 979252726Srpaulo const char *name; 980252726Srpaulo name = eap_get_name(cred->eap_method[0].vendor, 981252726Srpaulo cred->eap_method[0].method); 982281806Srpaulo if (name) 983281806Srpaulo fprintf(f, "\teap=%s\n", name); 984252726Srpaulo } 985252726Srpaulo if (cred->phase1) 986252726Srpaulo fprintf(f, "\tphase1=\"%s\"\n", cred->phase1); 987252726Srpaulo if (cred->phase2) 988252726Srpaulo fprintf(f, "\tphase2=\"%s\"\n", cred->phase2); 989252726Srpaulo if (cred->excluded_ssid) { 990281806Srpaulo size_t j; 991252726Srpaulo for (i = 0; i < cred->num_excluded_ssid; i++) { 992252726Srpaulo struct excluded_ssid *e = &cred->excluded_ssid[i]; 993252726Srpaulo fprintf(f, "\texcluded_ssid="); 994252726Srpaulo for (j = 0; j < e->ssid_len; j++) 995252726Srpaulo fprintf(f, "%02x", e->ssid[j]); 996252726Srpaulo fprintf(f, "\n"); 997252726Srpaulo } 998252726Srpaulo } 999281806Srpaulo if (cred->roaming_partner) { 1000281806Srpaulo for (i = 0; i < cred->num_roaming_partner; i++) { 1001281806Srpaulo struct roaming_partner *p = &cred->roaming_partner[i]; 1002281806Srpaulo fprintf(f, "\troaming_partner=\"%s,%d,%u,%s\"\n", 1003281806Srpaulo p->fqdn, p->exact_match, p->priority, 1004281806Srpaulo p->country); 1005281806Srpaulo } 1006281806Srpaulo } 1007281806Srpaulo if (cred->update_identifier) 1008281806Srpaulo fprintf(f, "\tupdate_identifier=%d\n", cred->update_identifier); 1009281806Srpaulo 1010281806Srpaulo if (cred->provisioning_sp) 1011281806Srpaulo fprintf(f, "\tprovisioning_sp=\"%s\"\n", cred->provisioning_sp); 1012281806Srpaulo if (cred->sp_priority) 1013281806Srpaulo fprintf(f, "\tsp_priority=%d\n", cred->sp_priority); 1014281806Srpaulo 1015281806Srpaulo if (cred->min_dl_bandwidth_home) 1016281806Srpaulo fprintf(f, "\tmin_dl_bandwidth_home=%u\n", 1017281806Srpaulo cred->min_dl_bandwidth_home); 1018281806Srpaulo if (cred->min_ul_bandwidth_home) 1019281806Srpaulo fprintf(f, "\tmin_ul_bandwidth_home=%u\n", 1020281806Srpaulo cred->min_ul_bandwidth_home); 1021281806Srpaulo if (cred->min_dl_bandwidth_roaming) 1022281806Srpaulo fprintf(f, "\tmin_dl_bandwidth_roaming=%u\n", 1023281806Srpaulo cred->min_dl_bandwidth_roaming); 1024281806Srpaulo if (cred->min_ul_bandwidth_roaming) 1025281806Srpaulo fprintf(f, "\tmin_ul_bandwidth_roaming=%u\n", 1026281806Srpaulo cred->min_ul_bandwidth_roaming); 1027281806Srpaulo 1028281806Srpaulo if (cred->max_bss_load) 1029281806Srpaulo fprintf(f, "\tmax_bss_load=%u\n", 1030281806Srpaulo cred->max_bss_load); 1031281806Srpaulo 1032281806Srpaulo if (cred->ocsp) 1033281806Srpaulo fprintf(f, "\tocsp=%d\n", cred->ocsp); 1034281806Srpaulo 1035281806Srpaulo if (cred->num_req_conn_capab) { 1036281806Srpaulo for (i = 0; i < cred->num_req_conn_capab; i++) { 1037281806Srpaulo int *ports; 1038281806Srpaulo 1039281806Srpaulo fprintf(f, "\treq_conn_capab=%u", 1040281806Srpaulo cred->req_conn_capab_proto[i]); 1041281806Srpaulo ports = cred->req_conn_capab_port[i]; 1042281806Srpaulo if (ports) { 1043281806Srpaulo int j; 1044281806Srpaulo for (j = 0; ports[j] != -1; j++) { 1045281806Srpaulo fprintf(f, "%s%d", j > 0 ? "," : ":", 1046281806Srpaulo ports[j]); 1047281806Srpaulo } 1048281806Srpaulo } 1049281806Srpaulo fprintf(f, "\n"); 1050281806Srpaulo } 1051281806Srpaulo } 1052281806Srpaulo 1053281806Srpaulo if (cred->required_roaming_consortium_len) { 1054281806Srpaulo fprintf(f, "\trequired_roaming_consortium="); 1055281806Srpaulo for (i = 0; i < cred->required_roaming_consortium_len; i++) 1056281806Srpaulo fprintf(f, "%02x", 1057281806Srpaulo cred->required_roaming_consortium[i]); 1058281806Srpaulo fprintf(f, "\n"); 1059281806Srpaulo } 1060281806Srpaulo 1061346981Scy if (cred->num_roaming_consortiums) { 1062346981Scy size_t j; 1063346981Scy 1064346981Scy fprintf(f, "\troaming_consortiums=\""); 1065346981Scy for (i = 0; i < cred->num_roaming_consortiums; i++) { 1066346981Scy if (i > 0) 1067346981Scy fprintf(f, ","); 1068346981Scy for (j = 0; j < cred->roaming_consortiums_len[i]; j++) 1069346981Scy fprintf(f, "%02x", 1070346981Scy cred->roaming_consortiums[i][j]); 1071346981Scy } 1072346981Scy fprintf(f, "\"\n"); 1073346981Scy } 1074346981Scy 1075281806Srpaulo if (cred->sim_num != DEFAULT_USER_SELECTED_SIM) 1076281806Srpaulo fprintf(f, "\tsim_num=%d\n", cred->sim_num); 1077252726Srpaulo} 1078252726Srpaulo 1079252726Srpaulo 1080189251Ssam#ifndef CONFIG_NO_CONFIG_BLOBS 1081189251Ssamstatic int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob) 1082189251Ssam{ 1083189251Ssam unsigned char *encoded; 1084189251Ssam 1085189251Ssam encoded = base64_encode(blob->data, blob->len, NULL); 1086189251Ssam if (encoded == NULL) 1087189251Ssam return -1; 1088189251Ssam 1089189251Ssam fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded); 1090189251Ssam os_free(encoded); 1091189251Ssam return 0; 1092189251Ssam} 1093189251Ssam#endif /* CONFIG_NO_CONFIG_BLOBS */ 1094189251Ssam 1095189251Ssam 1096252726Srpaulostatic void write_global_bin(FILE *f, const char *field, 1097252726Srpaulo const struct wpabuf *val) 1098252726Srpaulo{ 1099252726Srpaulo size_t i; 1100252726Srpaulo const u8 *pos; 1101252726Srpaulo 1102252726Srpaulo if (val == NULL) 1103252726Srpaulo return; 1104252726Srpaulo 1105252726Srpaulo fprintf(f, "%s=", field); 1106252726Srpaulo pos = wpabuf_head(val); 1107252726Srpaulo for (i = 0; i < wpabuf_len(val); i++) 1108252726Srpaulo fprintf(f, "%02X", *pos++); 1109252726Srpaulo fprintf(f, "\n"); 1110252726Srpaulo} 1111252726Srpaulo 1112252726Srpaulo 1113189251Ssamstatic void wpa_config_write_global(FILE *f, struct wpa_config *config) 1114189251Ssam{ 1115189251Ssam#ifdef CONFIG_CTRL_IFACE 1116189251Ssam if (config->ctrl_interface) 1117189251Ssam fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface); 1118189251Ssam if (config->ctrl_interface_group) 1119189251Ssam fprintf(f, "ctrl_interface_group=%s\n", 1120189251Ssam config->ctrl_interface_group); 1121189251Ssam#endif /* CONFIG_CTRL_IFACE */ 1122189251Ssam if (config->eapol_version != DEFAULT_EAPOL_VERSION) 1123189251Ssam fprintf(f, "eapol_version=%d\n", config->eapol_version); 1124189251Ssam if (config->ap_scan != DEFAULT_AP_SCAN) 1125189251Ssam fprintf(f, "ap_scan=%d\n", config->ap_scan); 1126252726Srpaulo if (config->disable_scan_offload) 1127252726Srpaulo fprintf(f, "disable_scan_offload=%d\n", 1128252726Srpaulo config->disable_scan_offload); 1129189251Ssam if (config->fast_reauth != DEFAULT_FAST_REAUTH) 1130189251Ssam fprintf(f, "fast_reauth=%d\n", config->fast_reauth); 1131189251Ssam if (config->opensc_engine_path) 1132189251Ssam fprintf(f, "opensc_engine_path=%s\n", 1133189251Ssam config->opensc_engine_path); 1134189251Ssam if (config->pkcs11_engine_path) 1135189251Ssam fprintf(f, "pkcs11_engine_path=%s\n", 1136189251Ssam config->pkcs11_engine_path); 1137189251Ssam if (config->pkcs11_module_path) 1138189251Ssam fprintf(f, "pkcs11_module_path=%s\n", 1139189251Ssam config->pkcs11_module_path); 1140281806Srpaulo if (config->openssl_ciphers) 1141281806Srpaulo fprintf(f, "openssl_ciphers=%s\n", config->openssl_ciphers); 1142252726Srpaulo if (config->pcsc_reader) 1143252726Srpaulo fprintf(f, "pcsc_reader=%s\n", config->pcsc_reader); 1144252726Srpaulo if (config->pcsc_pin) 1145252726Srpaulo fprintf(f, "pcsc_pin=%s\n", config->pcsc_pin); 1146189251Ssam if (config->driver_param) 1147189251Ssam fprintf(f, "driver_param=%s\n", config->driver_param); 1148189251Ssam if (config->dot11RSNAConfigPMKLifetime) 1149289549Srpaulo fprintf(f, "dot11RSNAConfigPMKLifetime=%u\n", 1150189251Ssam config->dot11RSNAConfigPMKLifetime); 1151189251Ssam if (config->dot11RSNAConfigPMKReauthThreshold) 1152289549Srpaulo fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%u\n", 1153189251Ssam config->dot11RSNAConfigPMKReauthThreshold); 1154189251Ssam if (config->dot11RSNAConfigSATimeout) 1155289549Srpaulo fprintf(f, "dot11RSNAConfigSATimeout=%u\n", 1156189251Ssam config->dot11RSNAConfigSATimeout); 1157189251Ssam if (config->update_config) 1158189251Ssam fprintf(f, "update_config=%d\n", config->update_config); 1159189251Ssam#ifdef CONFIG_WPS 1160189251Ssam if (!is_nil_uuid(config->uuid)) { 1161189251Ssam char buf[40]; 1162189251Ssam uuid_bin2str(config->uuid, buf, sizeof(buf)); 1163189251Ssam fprintf(f, "uuid=%s\n", buf); 1164189251Ssam } 1165346981Scy if (config->auto_uuid) 1166346981Scy fprintf(f, "auto_uuid=%d\n", config->auto_uuid); 1167189251Ssam if (config->device_name) 1168189251Ssam fprintf(f, "device_name=%s\n", config->device_name); 1169189251Ssam if (config->manufacturer) 1170189251Ssam fprintf(f, "manufacturer=%s\n", config->manufacturer); 1171189251Ssam if (config->model_name) 1172189251Ssam fprintf(f, "model_name=%s\n", config->model_name); 1173189251Ssam if (config->model_number) 1174189251Ssam fprintf(f, "model_number=%s\n", config->model_number); 1175189251Ssam if (config->serial_number) 1176189251Ssam fprintf(f, "serial_number=%s\n", config->serial_number); 1177252726Srpaulo { 1178252726Srpaulo char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; 1179252726Srpaulo buf = wps_dev_type_bin2str(config->device_type, 1180252726Srpaulo _buf, sizeof(_buf)); 1181252726Srpaulo if (os_strcmp(buf, "0-00000000-0") != 0) 1182252726Srpaulo fprintf(f, "device_type=%s\n", buf); 1183252726Srpaulo } 1184189251Ssam if (WPA_GET_BE32(config->os_version)) 1185189251Ssam fprintf(f, "os_version=%08x\n", 1186189251Ssam WPA_GET_BE32(config->os_version)); 1187214734Srpaulo if (config->config_methods) 1188214734Srpaulo fprintf(f, "config_methods=%s\n", config->config_methods); 1189189251Ssam if (config->wps_cred_processing) 1190189251Ssam fprintf(f, "wps_cred_processing=%d\n", 1191189251Ssam config->wps_cred_processing); 1192346981Scy if (config->wps_cred_add_sae) 1193346981Scy fprintf(f, "wps_cred_add_sae=%d\n", 1194346981Scy config->wps_cred_add_sae); 1195252726Srpaulo if (config->wps_vendor_ext_m1) { 1196252726Srpaulo int i, len = wpabuf_len(config->wps_vendor_ext_m1); 1197252726Srpaulo const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1); 1198252726Srpaulo if (len > 0) { 1199252726Srpaulo fprintf(f, "wps_vendor_ext_m1="); 1200252726Srpaulo for (i = 0; i < len; i++) 1201252726Srpaulo fprintf(f, "%02x", *p++); 1202252726Srpaulo fprintf(f, "\n"); 1203252726Srpaulo } 1204252726Srpaulo } 1205189251Ssam#endif /* CONFIG_WPS */ 1206252726Srpaulo#ifdef CONFIG_P2P 1207346981Scy { 1208346981Scy int i; 1209346981Scy char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; 1210346981Scy 1211346981Scy for (i = 0; i < config->num_sec_device_types; i++) { 1212346981Scy buf = wps_dev_type_bin2str(config->sec_device_type[i], 1213346981Scy _buf, sizeof(_buf)); 1214346981Scy if (buf) 1215346981Scy fprintf(f, "sec_device_type=%s\n", buf); 1216346981Scy } 1217346981Scy } 1218252726Srpaulo if (config->p2p_listen_reg_class) 1219289549Srpaulo fprintf(f, "p2p_listen_reg_class=%d\n", 1220252726Srpaulo config->p2p_listen_reg_class); 1221252726Srpaulo if (config->p2p_listen_channel) 1222289549Srpaulo fprintf(f, "p2p_listen_channel=%d\n", 1223252726Srpaulo config->p2p_listen_channel); 1224252726Srpaulo if (config->p2p_oper_reg_class) 1225289549Srpaulo fprintf(f, "p2p_oper_reg_class=%d\n", 1226252726Srpaulo config->p2p_oper_reg_class); 1227252726Srpaulo if (config->p2p_oper_channel) 1228289549Srpaulo fprintf(f, "p2p_oper_channel=%d\n", config->p2p_oper_channel); 1229252726Srpaulo if (config->p2p_go_intent != DEFAULT_P2P_GO_INTENT) 1230289549Srpaulo fprintf(f, "p2p_go_intent=%d\n", config->p2p_go_intent); 1231252726Srpaulo if (config->p2p_ssid_postfix) 1232252726Srpaulo fprintf(f, "p2p_ssid_postfix=%s\n", config->p2p_ssid_postfix); 1233252726Srpaulo if (config->persistent_reconnect) 1234289549Srpaulo fprintf(f, "persistent_reconnect=%d\n", 1235252726Srpaulo config->persistent_reconnect); 1236252726Srpaulo if (config->p2p_intra_bss != DEFAULT_P2P_INTRA_BSS) 1237289549Srpaulo fprintf(f, "p2p_intra_bss=%d\n", config->p2p_intra_bss); 1238252726Srpaulo if (config->p2p_group_idle) 1239289549Srpaulo fprintf(f, "p2p_group_idle=%d\n", config->p2p_group_idle); 1240281806Srpaulo if (config->p2p_passphrase_len) 1241281806Srpaulo fprintf(f, "p2p_passphrase_len=%u\n", 1242281806Srpaulo config->p2p_passphrase_len); 1243252726Srpaulo if (config->p2p_pref_chan) { 1244252726Srpaulo unsigned int i; 1245252726Srpaulo fprintf(f, "p2p_pref_chan="); 1246252726Srpaulo for (i = 0; i < config->num_p2p_pref_chan; i++) { 1247252726Srpaulo fprintf(f, "%s%u:%u", i > 0 ? "," : "", 1248252726Srpaulo config->p2p_pref_chan[i].op_class, 1249252726Srpaulo config->p2p_pref_chan[i].chan); 1250252726Srpaulo } 1251252726Srpaulo fprintf(f, "\n"); 1252252726Srpaulo } 1253281806Srpaulo if (config->p2p_no_go_freq.num) { 1254281806Srpaulo char *val = freq_range_list_str(&config->p2p_no_go_freq); 1255281806Srpaulo if (val) { 1256281806Srpaulo fprintf(f, "p2p_no_go_freq=%s\n", val); 1257281806Srpaulo os_free(val); 1258281806Srpaulo } 1259281806Srpaulo } 1260281806Srpaulo if (config->p2p_add_cli_chan) 1261281806Srpaulo fprintf(f, "p2p_add_cli_chan=%d\n", config->p2p_add_cli_chan); 1262281806Srpaulo if (config->p2p_optimize_listen_chan != 1263281806Srpaulo DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN) 1264281806Srpaulo fprintf(f, "p2p_optimize_listen_chan=%d\n", 1265281806Srpaulo config->p2p_optimize_listen_chan); 1266252726Srpaulo if (config->p2p_go_ht40) 1267289549Srpaulo fprintf(f, "p2p_go_ht40=%d\n", config->p2p_go_ht40); 1268281806Srpaulo if (config->p2p_go_vht) 1269289549Srpaulo fprintf(f, "p2p_go_vht=%d\n", config->p2p_go_vht); 1270346981Scy if (config->p2p_go_he) 1271346981Scy fprintf(f, "p2p_go_he=%d\n", config->p2p_go_he); 1272281806Srpaulo if (config->p2p_go_ctwindow != DEFAULT_P2P_GO_CTWINDOW) 1273289549Srpaulo fprintf(f, "p2p_go_ctwindow=%d\n", config->p2p_go_ctwindow); 1274252726Srpaulo if (config->p2p_disabled) 1275289549Srpaulo fprintf(f, "p2p_disabled=%d\n", config->p2p_disabled); 1276252726Srpaulo if (config->p2p_no_group_iface) 1277289549Srpaulo fprintf(f, "p2p_no_group_iface=%d\n", 1278252726Srpaulo config->p2p_no_group_iface); 1279281806Srpaulo if (config->p2p_ignore_shared_freq) 1280289549Srpaulo fprintf(f, "p2p_ignore_shared_freq=%d\n", 1281281806Srpaulo config->p2p_ignore_shared_freq); 1282289549Srpaulo if (config->p2p_cli_probe) 1283289549Srpaulo fprintf(f, "p2p_cli_probe=%d\n", config->p2p_cli_probe); 1284289549Srpaulo if (config->p2p_go_freq_change_policy != DEFAULT_P2P_GO_FREQ_MOVE) 1285289549Srpaulo fprintf(f, "p2p_go_freq_change_policy=%u\n", 1286289549Srpaulo config->p2p_go_freq_change_policy); 1287337817Scy if (WPA_GET_BE32(config->ip_addr_go)) 1288337817Scy fprintf(f, "ip_addr_go=%u.%u.%u.%u\n", 1289337817Scy config->ip_addr_go[0], config->ip_addr_go[1], 1290337817Scy config->ip_addr_go[2], config->ip_addr_go[3]); 1291337817Scy if (WPA_GET_BE32(config->ip_addr_mask)) 1292337817Scy fprintf(f, "ip_addr_mask=%u.%u.%u.%u\n", 1293337817Scy config->ip_addr_mask[0], config->ip_addr_mask[1], 1294337817Scy config->ip_addr_mask[2], config->ip_addr_mask[3]); 1295337817Scy if (WPA_GET_BE32(config->ip_addr_start)) 1296337817Scy fprintf(f, "ip_addr_start=%u.%u.%u.%u\n", 1297337817Scy config->ip_addr_start[0], config->ip_addr_start[1], 1298337817Scy config->ip_addr_start[2], config->ip_addr_start[3]); 1299337817Scy if (WPA_GET_BE32(config->ip_addr_end)) 1300337817Scy fprintf(f, "ip_addr_end=%u.%u.%u.%u\n", 1301337817Scy config->ip_addr_end[0], config->ip_addr_end[1], 1302337817Scy config->ip_addr_end[2], config->ip_addr_end[3]); 1303252726Srpaulo#endif /* CONFIG_P2P */ 1304189251Ssam if (config->country[0] && config->country[1]) { 1305189251Ssam fprintf(f, "country=%c%c\n", 1306189251Ssam config->country[0], config->country[1]); 1307189251Ssam } 1308214734Srpaulo if (config->bss_max_count != DEFAULT_BSS_MAX_COUNT) 1309214734Srpaulo fprintf(f, "bss_max_count=%u\n", config->bss_max_count); 1310252726Srpaulo if (config->bss_expiration_age != DEFAULT_BSS_EXPIRATION_AGE) 1311252726Srpaulo fprintf(f, "bss_expiration_age=%u\n", 1312252726Srpaulo config->bss_expiration_age); 1313252726Srpaulo if (config->bss_expiration_scan_count != 1314252726Srpaulo DEFAULT_BSS_EXPIRATION_SCAN_COUNT) 1315252726Srpaulo fprintf(f, "bss_expiration_scan_count=%u\n", 1316252726Srpaulo config->bss_expiration_scan_count); 1317214734Srpaulo if (config->filter_ssids) 1318214734Srpaulo fprintf(f, "filter_ssids=%d\n", config->filter_ssids); 1319346981Scy if (config->filter_rssi) 1320346981Scy fprintf(f, "filter_rssi=%d\n", config->filter_rssi); 1321252726Srpaulo if (config->max_num_sta != DEFAULT_MAX_NUM_STA) 1322252726Srpaulo fprintf(f, "max_num_sta=%u\n", config->max_num_sta); 1323346981Scy if (config->ap_isolate != DEFAULT_AP_ISOLATE) 1324346981Scy fprintf(f, "ap_isolate=%u\n", config->ap_isolate); 1325252726Srpaulo if (config->disassoc_low_ack) 1326289549Srpaulo fprintf(f, "disassoc_low_ack=%d\n", config->disassoc_low_ack); 1327252726Srpaulo#ifdef CONFIG_HS20 1328252726Srpaulo if (config->hs20) 1329252726Srpaulo fprintf(f, "hs20=1\n"); 1330252726Srpaulo#endif /* CONFIG_HS20 */ 1331252726Srpaulo#ifdef CONFIG_INTERWORKING 1332252726Srpaulo if (config->interworking) 1333289549Srpaulo fprintf(f, "interworking=%d\n", config->interworking); 1334252726Srpaulo if (!is_zero_ether_addr(config->hessid)) 1335252726Srpaulo fprintf(f, "hessid=" MACSTR "\n", MAC2STR(config->hessid)); 1336252726Srpaulo if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE) 1337252726Srpaulo fprintf(f, "access_network_type=%d\n", 1338252726Srpaulo config->access_network_type); 1339346981Scy if (config->go_interworking) 1340346981Scy fprintf(f, "go_interworking=%d\n", config->go_interworking); 1341346981Scy if (config->go_access_network_type) 1342346981Scy fprintf(f, "go_access_network_type=%d\n", 1343346981Scy config->go_access_network_type); 1344346981Scy if (config->go_internet) 1345346981Scy fprintf(f, "go_internet=%d\n", config->go_internet); 1346346981Scy if (config->go_venue_group) 1347346981Scy fprintf(f, "go_venue_group=%d\n", config->go_venue_group); 1348346981Scy if (config->go_venue_type) 1349346981Scy fprintf(f, "go_venue_type=%d\n", config->go_venue_type); 1350252726Srpaulo#endif /* CONFIG_INTERWORKING */ 1351252726Srpaulo if (config->pbc_in_m1) 1352289549Srpaulo fprintf(f, "pbc_in_m1=%d\n", config->pbc_in_m1); 1353281806Srpaulo if (config->wps_nfc_pw_from_config) { 1354281806Srpaulo if (config->wps_nfc_dev_pw_id) 1355281806Srpaulo fprintf(f, "wps_nfc_dev_pw_id=%d\n", 1356281806Srpaulo config->wps_nfc_dev_pw_id); 1357281806Srpaulo write_global_bin(f, "wps_nfc_dh_pubkey", 1358281806Srpaulo config->wps_nfc_dh_pubkey); 1359281806Srpaulo write_global_bin(f, "wps_nfc_dh_privkey", 1360281806Srpaulo config->wps_nfc_dh_privkey); 1361281806Srpaulo write_global_bin(f, "wps_nfc_dev_pw", config->wps_nfc_dev_pw); 1362281806Srpaulo } 1363252726Srpaulo 1364252726Srpaulo if (config->ext_password_backend) 1365252726Srpaulo fprintf(f, "ext_password_backend=%s\n", 1366252726Srpaulo config->ext_password_backend); 1367252726Srpaulo if (config->p2p_go_max_inactivity != DEFAULT_P2P_GO_MAX_INACTIVITY) 1368252726Srpaulo fprintf(f, "p2p_go_max_inactivity=%d\n", 1369252726Srpaulo config->p2p_go_max_inactivity); 1370252726Srpaulo if (config->auto_interworking) 1371252726Srpaulo fprintf(f, "auto_interworking=%d\n", 1372252726Srpaulo config->auto_interworking); 1373252726Srpaulo if (config->okc) 1374252726Srpaulo fprintf(f, "okc=%d\n", config->okc); 1375252726Srpaulo if (config->pmf) 1376252726Srpaulo fprintf(f, "pmf=%d\n", config->pmf); 1377281806Srpaulo if (config->dtim_period) 1378281806Srpaulo fprintf(f, "dtim_period=%d\n", config->dtim_period); 1379281806Srpaulo if (config->beacon_int) 1380281806Srpaulo fprintf(f, "beacon_int=%d\n", config->beacon_int); 1381281806Srpaulo 1382281806Srpaulo if (config->sae_groups) { 1383281806Srpaulo int i; 1384281806Srpaulo fprintf(f, "sae_groups="); 1385346981Scy for (i = 0; config->sae_groups[i] > 0; i++) { 1386281806Srpaulo fprintf(f, "%s%d", i > 0 ? " " : "", 1387281806Srpaulo config->sae_groups[i]); 1388281806Srpaulo } 1389281806Srpaulo fprintf(f, "\n"); 1390281806Srpaulo } 1391281806Srpaulo 1392281806Srpaulo if (config->ap_vendor_elements) { 1393281806Srpaulo int i, len = wpabuf_len(config->ap_vendor_elements); 1394281806Srpaulo const u8 *p = wpabuf_head_u8(config->ap_vendor_elements); 1395281806Srpaulo if (len > 0) { 1396281806Srpaulo fprintf(f, "ap_vendor_elements="); 1397281806Srpaulo for (i = 0; i < len; i++) 1398281806Srpaulo fprintf(f, "%02x", *p++); 1399281806Srpaulo fprintf(f, "\n"); 1400281806Srpaulo } 1401281806Srpaulo } 1402281806Srpaulo 1403281806Srpaulo if (config->ignore_old_scan_res) 1404281806Srpaulo fprintf(f, "ignore_old_scan_res=%d\n", 1405281806Srpaulo config->ignore_old_scan_res); 1406281806Srpaulo 1407281806Srpaulo if (config->freq_list && config->freq_list[0]) { 1408281806Srpaulo int i; 1409281806Srpaulo fprintf(f, "freq_list="); 1410281806Srpaulo for (i = 0; config->freq_list[i]; i++) { 1411289549Srpaulo fprintf(f, "%s%d", i > 0 ? " " : "", 1412281806Srpaulo config->freq_list[i]); 1413281806Srpaulo } 1414281806Srpaulo fprintf(f, "\n"); 1415281806Srpaulo } 1416281806Srpaulo if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ) 1417281806Srpaulo fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq); 1418281806Srpaulo 1419281806Srpaulo if (config->sched_scan_interval) 1420281806Srpaulo fprintf(f, "sched_scan_interval=%u\n", 1421281806Srpaulo config->sched_scan_interval); 1422281806Srpaulo 1423346981Scy if (config->sched_scan_start_delay) 1424346981Scy fprintf(f, "sched_scan_start_delay=%u\n", 1425346981Scy config->sched_scan_start_delay); 1426346981Scy 1427281806Srpaulo if (config->external_sim) 1428281806Srpaulo fprintf(f, "external_sim=%d\n", config->external_sim); 1429281806Srpaulo 1430281806Srpaulo if (config->tdls_external_control) 1431281806Srpaulo fprintf(f, "tdls_external_control=%d\n", 1432281806Srpaulo config->tdls_external_control); 1433281806Srpaulo 1434281806Srpaulo if (config->wowlan_triggers) 1435281806Srpaulo fprintf(f, "wowlan_triggers=%s\n", 1436281806Srpaulo config->wowlan_triggers); 1437281806Srpaulo 1438281806Srpaulo if (config->bgscan) 1439281806Srpaulo fprintf(f, "bgscan=\"%s\"\n", config->bgscan); 1440281806Srpaulo 1441346981Scy if (config->autoscan) 1442346981Scy fprintf(f, "autoscan=%s\n", config->autoscan); 1443346981Scy 1444281806Srpaulo if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY) 1445281806Srpaulo fprintf(f, "p2p_search_delay=%u\n", 1446281806Srpaulo config->p2p_search_delay); 1447281806Srpaulo 1448281806Srpaulo if (config->mac_addr) 1449281806Srpaulo fprintf(f, "mac_addr=%d\n", config->mac_addr); 1450281806Srpaulo 1451281806Srpaulo if (config->rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME) 1452281806Srpaulo fprintf(f, "rand_addr_lifetime=%u\n", 1453281806Srpaulo config->rand_addr_lifetime); 1454281806Srpaulo 1455281806Srpaulo if (config->preassoc_mac_addr) 1456281806Srpaulo fprintf(f, "preassoc_mac_addr=%d\n", config->preassoc_mac_addr); 1457281806Srpaulo 1458281806Srpaulo if (config->key_mgmt_offload != DEFAULT_KEY_MGMT_OFFLOAD) 1459289549Srpaulo fprintf(f, "key_mgmt_offload=%d\n", config->key_mgmt_offload); 1460281806Srpaulo 1461281806Srpaulo if (config->user_mpm != DEFAULT_USER_MPM) 1462281806Srpaulo fprintf(f, "user_mpm=%d\n", config->user_mpm); 1463281806Srpaulo 1464281806Srpaulo if (config->max_peer_links != DEFAULT_MAX_PEER_LINKS) 1465281806Srpaulo fprintf(f, "max_peer_links=%d\n", config->max_peer_links); 1466281806Srpaulo 1467281806Srpaulo if (config->cert_in_cb != DEFAULT_CERT_IN_CB) 1468281806Srpaulo fprintf(f, "cert_in_cb=%d\n", config->cert_in_cb); 1469281806Srpaulo 1470281806Srpaulo if (config->mesh_max_inactivity != DEFAULT_MESH_MAX_INACTIVITY) 1471281806Srpaulo fprintf(f, "mesh_max_inactivity=%d\n", 1472281806Srpaulo config->mesh_max_inactivity); 1473281806Srpaulo 1474289549Srpaulo if (config->dot11RSNASAERetransPeriod != 1475289549Srpaulo DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD) 1476289549Srpaulo fprintf(f, "dot11RSNASAERetransPeriod=%d\n", 1477289549Srpaulo config->dot11RSNASAERetransPeriod); 1478289549Srpaulo 1479281806Srpaulo if (config->passive_scan) 1480281806Srpaulo fprintf(f, "passive_scan=%d\n", config->passive_scan); 1481281806Srpaulo 1482281806Srpaulo if (config->reassoc_same_bss_optim) 1483281806Srpaulo fprintf(f, "reassoc_same_bss_optim=%d\n", 1484281806Srpaulo config->reassoc_same_bss_optim); 1485289549Srpaulo 1486289549Srpaulo if (config->wps_priority) 1487289549Srpaulo fprintf(f, "wps_priority=%d\n", config->wps_priority); 1488337817Scy 1489337817Scy if (config->wpa_rsc_relaxation != DEFAULT_WPA_RSC_RELAXATION) 1490337817Scy fprintf(f, "wpa_rsc_relaxation=%d\n", 1491337817Scy config->wpa_rsc_relaxation); 1492337817Scy 1493337817Scy if (config->sched_scan_plans) 1494337817Scy fprintf(f, "sched_scan_plans=%s\n", config->sched_scan_plans); 1495337817Scy 1496337817Scy#ifdef CONFIG_MBO 1497337817Scy if (config->non_pref_chan) 1498337817Scy fprintf(f, "non_pref_chan=%s\n", config->non_pref_chan); 1499337817Scy if (config->mbo_cell_capa != DEFAULT_MBO_CELL_CAPA) 1500337817Scy fprintf(f, "mbo_cell_capa=%u\n", config->mbo_cell_capa); 1501346981Scy if (config->disassoc_imminent_rssi_threshold != 1502346981Scy DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD) 1503346981Scy fprintf(f, "disassoc_imminent_rssi_threshold=%d\n", 1504346981Scy config->disassoc_imminent_rssi_threshold); 1505346981Scy if (config->oce != DEFAULT_OCE_SUPPORT) 1506346981Scy fprintf(f, "oce=%u\n", config->oce); 1507337817Scy#endif /* CONFIG_MBO */ 1508337817Scy 1509337817Scy if (config->gas_address3) 1510337817Scy fprintf(f, "gas_address3=%d\n", config->gas_address3); 1511337817Scy 1512337817Scy if (config->ftm_responder) 1513337817Scy fprintf(f, "ftm_responder=%d\n", config->ftm_responder); 1514337817Scy if (config->ftm_initiator) 1515337817Scy fprintf(f, "ftm_initiator=%d\n", config->ftm_initiator); 1516346981Scy 1517346981Scy if (config->osu_dir) 1518346981Scy fprintf(f, "osu_dir=%s\n", config->osu_dir); 1519346981Scy 1520346981Scy if (config->fst_group_id) 1521346981Scy fprintf(f, "fst_group_id=%s\n", config->fst_group_id); 1522346981Scy if (config->fst_priority) 1523346981Scy fprintf(f, "fst_priority=%d\n", config->fst_priority); 1524346981Scy if (config->fst_llt) 1525346981Scy fprintf(f, "fst_llt=%d\n", config->fst_llt); 1526346981Scy 1527346981Scy if (config->gas_rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME) 1528346981Scy fprintf(f, "gas_rand_addr_lifetime=%u\n", 1529346981Scy config->gas_rand_addr_lifetime); 1530346981Scy if (config->gas_rand_mac_addr) 1531346981Scy fprintf(f, "gas_rand_mac_addr=%d\n", config->gas_rand_mac_addr); 1532346981Scy if (config->dpp_config_processing) 1533346981Scy fprintf(f, "dpp_config_processing=%d\n", 1534346981Scy config->dpp_config_processing); 1535346981Scy if (config->coloc_intf_reporting) 1536346981Scy fprintf(f, "coloc_intf_reporting=%d\n", 1537346981Scy config->coloc_intf_reporting); 1538346981Scy if (config->p2p_device_random_mac_addr) 1539346981Scy fprintf(f, "p2p_device_random_mac_addr=%d\n", 1540346981Scy config->p2p_device_random_mac_addr); 1541346981Scy if (!is_zero_ether_addr(config->p2p_device_persistent_mac_addr)) 1542346981Scy fprintf(f, "p2p_device_persistent_mac_addr=" MACSTR "\n", 1543346981Scy MAC2STR(config->p2p_device_persistent_mac_addr)); 1544346981Scy if (config->p2p_interface_random_mac_addr) 1545346981Scy fprintf(f, "p2p_interface_random_mac_addr=%d\n", 1546346981Scy config->p2p_interface_random_mac_addr); 1547189251Ssam} 1548189251Ssam 1549189251Ssam#endif /* CONFIG_NO_CONFIG_WRITE */ 1550189251Ssam 1551189251Ssam 1552189251Ssamint wpa_config_write(const char *name, struct wpa_config *config) 1553189251Ssam{ 1554189251Ssam#ifndef CONFIG_NO_CONFIG_WRITE 1555189251Ssam FILE *f; 1556189251Ssam struct wpa_ssid *ssid; 1557252726Srpaulo struct wpa_cred *cred; 1558189251Ssam#ifndef CONFIG_NO_CONFIG_BLOBS 1559189251Ssam struct wpa_config_blob *blob; 1560189251Ssam#endif /* CONFIG_NO_CONFIG_BLOBS */ 1561189251Ssam int ret = 0; 1562281806Srpaulo const char *orig_name = name; 1563281806Srpaulo int tmp_len = os_strlen(name) + 5; /* allow space for .tmp suffix */ 1564281806Srpaulo char *tmp_name = os_malloc(tmp_len); 1565189251Ssam 1566281806Srpaulo if (tmp_name) { 1567281806Srpaulo os_snprintf(tmp_name, tmp_len, "%s.tmp", name); 1568281806Srpaulo name = tmp_name; 1569281806Srpaulo } 1570281806Srpaulo 1571189251Ssam wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); 1572189251Ssam 1573189251Ssam f = fopen(name, "w"); 1574189251Ssam if (f == NULL) { 1575189251Ssam wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name); 1576281806Srpaulo os_free(tmp_name); 1577189251Ssam return -1; 1578189251Ssam } 1579189251Ssam 1580189251Ssam wpa_config_write_global(f, config); 1581189251Ssam 1582252726Srpaulo for (cred = config->cred; cred; cred = cred->next) { 1583281806Srpaulo if (cred->temporary) 1584281806Srpaulo continue; 1585252726Srpaulo fprintf(f, "\ncred={\n"); 1586252726Srpaulo wpa_config_write_cred(f, cred); 1587252726Srpaulo fprintf(f, "}\n"); 1588252726Srpaulo } 1589252726Srpaulo 1590189251Ssam for (ssid = config->ssid; ssid; ssid = ssid->next) { 1591252726Srpaulo if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary) 1592252726Srpaulo continue; /* do not save temporary networks */ 1593252726Srpaulo if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && 1594252726Srpaulo !ssid->passphrase) 1595252726Srpaulo continue; /* do not save invalid network */ 1596189251Ssam fprintf(f, "\nnetwork={\n"); 1597189251Ssam wpa_config_write_network(f, ssid); 1598189251Ssam fprintf(f, "}\n"); 1599189251Ssam } 1600189251Ssam 1601189251Ssam#ifndef CONFIG_NO_CONFIG_BLOBS 1602189251Ssam for (blob = config->blobs; blob; blob = blob->next) { 1603189251Ssam ret = wpa_config_write_blob(f, blob); 1604189251Ssam if (ret) 1605189251Ssam break; 1606189251Ssam } 1607189251Ssam#endif /* CONFIG_NO_CONFIG_BLOBS */ 1608189251Ssam 1609289549Srpaulo os_fdatasync(f); 1610289549Srpaulo 1611189251Ssam fclose(f); 1612189251Ssam 1613281806Srpaulo if (tmp_name) { 1614281806Srpaulo int chmod_ret = 0; 1615281806Srpaulo 1616281806Srpaulo#ifdef ANDROID 1617281806Srpaulo chmod_ret = chmod(tmp_name, 1618281806Srpaulo S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 1619281806Srpaulo#endif /* ANDROID */ 1620281806Srpaulo if (chmod_ret != 0 || rename(tmp_name, orig_name) != 0) 1621281806Srpaulo ret = -1; 1622281806Srpaulo 1623281806Srpaulo os_free(tmp_name); 1624281806Srpaulo } 1625281806Srpaulo 1626189251Ssam wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully", 1627281806Srpaulo orig_name, ret ? "un" : ""); 1628189251Ssam return ret; 1629189251Ssam#else /* CONFIG_NO_CONFIG_WRITE */ 1630189251Ssam return -1; 1631189251Ssam#endif /* CONFIG_NO_CONFIG_WRITE */ 1632189251Ssam} 1633