2 * WPA Supplicant / Configuration parser and common functions
3 * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
22 #include "wpa_supplicant.h"
25 #include "l2_packet.h"
30 * Structure for network configuration parsing. This data is used to implement
31 * a generic parser for each network block variable. The table of configuration
32 * variables is defined below in this file (ssid_fields[]).
35 /* Configuration variable name */
38 /* Parser function for this variable */
39 int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
40 int line, const char *value);
42 /* Writer function (i.e., to get the variable in text format from
43 * internal presentation). */
44 char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
46 /* Variable specific parameters for the parser. */
47 void *param1, *param2, *param3, *param4;
49 /* 0 = this variable can be included in debug output
50 * 1 = this variable contains key/private data and it must not be
51 * included in debug output unless explicitly requested
57 static char * wpa_config_parse_string(const char *value, size_t *len)
62 pos = strchr(value, '"');
63 if (pos == NULL || pos[1] != '\0')
70 size_t hlen = strlen(value);
77 if (hexstr2bin(value, str, *len)) {
86 static int wpa_config_parse_str(const struct parse_data *data,
87 struct wpa_ssid *ssid,
88 int line, const char *value)
90 size_t res_len, *dst_len;
93 dst = (char **) (((u8 *) ssid) + (long) data->param1);
94 dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
97 *dst = wpa_config_parse_string(value, &res_len);
99 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
100 line, data->name, value);
106 if (data->key_data) {
107 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
108 (u8 *) *dst, res_len);
110 wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
111 (u8 *) *dst, res_len);
114 if (data->param3 && res_len < (size_t) data->param3) {
115 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
116 "min_len=%ld)", line, data->name,
117 (unsigned long) res_len, (long) data->param3);
123 if (data->param4 && res_len > (size_t) data->param4) {
124 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
125 "max_len=%ld)", line, data->name,
126 (unsigned long) res_len, (long) data->param4);
136 static int is_hex(const u8 *data, size_t len)
140 for (i = 0; i < len; i++) {
141 if (data[i] < 32 || data[i] >= 127)
148 static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
151 char *buf, *pos, *end;
153 pos = buf = malloc(len + 3);
157 pos += snprintf(pos, end - pos, "\"");
158 for (i = 0; i < len; i++)
159 pos += snprintf(pos, end - pos, "%c", value[i]);
160 pos += snprintf(pos, end - pos, "\"");
166 static char * wpa_config_write_string_hex(const u8 *value, size_t len)
169 char *buf, *pos, *end;
171 pos = buf = malloc(2 * len + 1);
174 memset(buf, 0, 2 * len + 1);
175 end = buf + 2 * len + 1;
176 for (i = 0; i < len; i++)
177 pos += snprintf(pos, end - pos, "%02x", value[i]);
183 static char * wpa_config_write_string(const u8 *value, size_t len)
188 if (is_hex(value, len))
189 return wpa_config_write_string_hex(value, len);
191 return wpa_config_write_string_ascii(value, len);
195 static char * wpa_config_write_str(const struct parse_data *data,
196 struct wpa_ssid *ssid)
201 src = (char **) (((u8 *) ssid) + (long) data->param1);
206 len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
210 return wpa_config_write_string((const u8 *) *src, len);
214 static int wpa_config_parse_int(const struct parse_data *data,
215 struct wpa_ssid *ssid,
216 int line, const char *value)
220 dst = (int *) (((u8 *) ssid) + (long) data->param1);
222 wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
224 if (data->param3 && *dst < (long) data->param3) {
225 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
226 "min_value=%ld)", line, data->name, *dst,
227 (long) data->param3);
228 *dst = (long) data->param3;
232 if (data->param4 && *dst > (long) data->param4) {
233 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
234 "max_value=%ld)", line, data->name, *dst,
235 (long) data->param4);
236 *dst = (long) data->param4;
244 static char * wpa_config_write_int(const struct parse_data *data,
245 struct wpa_ssid *ssid)
250 src = (int *) (((u8 *) ssid) + (long) data->param1);
255 snprintf(value, 20, "%d", *src);
260 static int wpa_config_parse_bssid(const struct parse_data *data,
261 struct wpa_ssid *ssid, int line,
264 if (hwaddr_aton(value, ssid->bssid)) {
265 wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
270 wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
275 static char * wpa_config_write_bssid(const struct parse_data *data,
276 struct wpa_ssid *ssid)
280 if (!ssid->bssid_set)
286 snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
291 static int wpa_config_parse_psk(const struct parse_data *data,
292 struct wpa_ssid *ssid, int line,
300 pos = strrchr(value, '"');
304 if (len < 8 || len > 63) {
305 wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
306 "length %lu (expected: 8..63) '%s'.",
307 line, (unsigned long) len, value);
310 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
312 ssid->passphrase = strdup(value);
313 return ssid->passphrase == NULL ? -1 : 0;
316 if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
317 value[PMK_LEN * 2] != '\0') {
318 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
323 wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
328 static char * wpa_config_write_psk(const struct parse_data *data,
329 struct wpa_ssid *ssid)
331 if (ssid->passphrase)
332 return wpa_config_write_string_ascii(
333 (const u8 *) ssid->passphrase,
334 strlen(ssid->passphrase));
337 return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
343 static int wpa_config_parse_proto(const struct parse_data *data,
344 struct wpa_ssid *ssid, int line,
347 int val = 0, last, errors = 0;
348 char *start, *end, *buf;
355 while (*start != '\0') {
356 while (*start == ' ' || *start == '\t')
361 while (*end != ' ' && *end != '\t' && *end != '\0')
365 if (strcmp(start, "WPA") == 0)
366 val |= WPA_PROTO_WPA;
367 else if (strcmp(start, "RSN") == 0 ||
368 strcmp(start, "WPA2") == 0)
369 val |= WPA_PROTO_RSN;
371 wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
383 wpa_printf(MSG_ERROR,
384 "Line %d: no proto values configured.", line);
388 wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
390 return errors ? -1 : 0;
394 static char * wpa_config_write_proto(const struct parse_data *data,
395 struct wpa_ssid *ssid)
398 char *buf, *pos, *end;
400 pos = buf = malloc(10);
406 if (ssid->proto & WPA_PROTO_WPA) {
407 pos += snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
411 if (ssid->proto & WPA_PROTO_RSN) {
412 pos += snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
420 static int wpa_config_parse_key_mgmt(const struct parse_data *data,
421 struct wpa_ssid *ssid, int line,
424 int val = 0, last, errors = 0;
425 char *start, *end, *buf;
432 while (*start != '\0') {
433 while (*start == ' ' || *start == '\t')
438 while (*end != ' ' && *end != '\t' && *end != '\0')
442 if (strcmp(start, "WPA-PSK") == 0)
443 val |= WPA_KEY_MGMT_PSK;
444 else if (strcmp(start, "WPA-EAP") == 0)
445 val |= WPA_KEY_MGMT_IEEE8021X;
446 else if (strcmp(start, "IEEE8021X") == 0)
447 val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
448 else if (strcmp(start, "NONE") == 0)
449 val |= WPA_KEY_MGMT_NONE;
450 else if (strcmp(start, "WPA-NONE") == 0)
451 val |= WPA_KEY_MGMT_WPA_NONE;
453 wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
465 wpa_printf(MSG_ERROR,
466 "Line %d: no key_mgmt values configured.", line);
470 wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
471 ssid->key_mgmt = val;
472 return errors ? -1 : 0;
476 static char * wpa_config_write_key_mgmt(const struct parse_data *data,
477 struct wpa_ssid *ssid)
480 char *buf, *pos, *end;
482 pos = buf = malloc(50);
488 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
489 pos += snprintf(pos, end - pos, "%sWPA-PSK", first ? "" : " ");
493 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
494 pos += snprintf(pos, end - pos, "%sWPA-EAP", first ? "" : " ");
498 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
499 pos += snprintf(pos, end - pos, "%sIEEE8021X",
504 if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
505 pos += snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
509 if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
510 pos += snprintf(pos, end - pos, "%sWPA-NONE",
519 static int wpa_config_parse_cipher(int line, const char *value)
522 char *start, *end, *buf;
529 while (*start != '\0') {
530 while (*start == ' ' || *start == '\t')
535 while (*end != ' ' && *end != '\t' && *end != '\0')
539 if (strcmp(start, "CCMP") == 0)
540 val |= WPA_CIPHER_CCMP;
541 else if (strcmp(start, "TKIP") == 0)
542 val |= WPA_CIPHER_TKIP;
543 else if (strcmp(start, "WEP104") == 0)
544 val |= WPA_CIPHER_WEP104;
545 else if (strcmp(start, "WEP40") == 0)
546 val |= WPA_CIPHER_WEP40;
547 else if (strcmp(start, "NONE") == 0)
548 val |= WPA_CIPHER_NONE;
550 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
563 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
571 static char * wpa_config_write_cipher(int cipher)
574 char *buf, *pos, *end;
576 pos = buf = malloc(50);
582 if (cipher & WPA_CIPHER_CCMP) {
583 pos += snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
587 if (cipher & WPA_CIPHER_TKIP) {
588 pos += snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
592 if (cipher & WPA_CIPHER_WEP104) {
593 pos += snprintf(pos, end - pos, "%sWEP104", first ? "" : " ");
597 if (cipher & WPA_CIPHER_WEP40) {
598 pos += snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
602 if (cipher & WPA_CIPHER_NONE) {
603 pos += snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
611 static int wpa_config_parse_pairwise(const struct parse_data *data,
612 struct wpa_ssid *ssid, int line,
616 val = wpa_config_parse_cipher(line, value);
619 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) {
620 wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
621 "(0x%x).", line, val);
625 wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
626 ssid->pairwise_cipher = val;
631 static char * wpa_config_write_pairwise(const struct parse_data *data,
632 struct wpa_ssid *ssid)
634 return wpa_config_write_cipher(ssid->pairwise_cipher);
638 static int wpa_config_parse_group(const struct parse_data *data,
639 struct wpa_ssid *ssid, int line,
643 val = wpa_config_parse_cipher(line, value);
646 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 |
648 wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
649 "(0x%x).", line, val);
653 wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
654 ssid->group_cipher = val;
659 static char * wpa_config_write_group(const struct parse_data *data,
660 struct wpa_ssid *ssid)
662 return wpa_config_write_cipher(ssid->group_cipher);
666 static int wpa_config_parse_auth_alg(const struct parse_data *data,
667 struct wpa_ssid *ssid, int line,
670 int val = 0, last, errors = 0;
671 char *start, *end, *buf;
678 while (*start != '\0') {
679 while (*start == ' ' || *start == '\t')
684 while (*end != ' ' && *end != '\t' && *end != '\0')
688 if (strcmp(start, "OPEN") == 0)
689 val |= WPA_AUTH_ALG_OPEN;
690 else if (strcmp(start, "SHARED") == 0)
691 val |= WPA_AUTH_ALG_SHARED;
692 else if (strcmp(start, "LEAP") == 0)
693 val |= WPA_AUTH_ALG_LEAP;
695 wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
707 wpa_printf(MSG_ERROR,
708 "Line %d: no auth_alg values configured.", line);
712 wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
713 ssid->auth_alg = val;
714 return errors ? -1 : 0;
718 static char * wpa_config_write_auth_alg(const struct parse_data *data,
719 struct wpa_ssid *ssid)
722 char *buf, *pos, *end;
724 pos = buf = malloc(30);
730 if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
731 pos += snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
735 if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
736 pos += snprintf(pos, end - pos, "%sSHARED", first ? "" : " ");
740 if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
741 pos += snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
749 static int wpa_config_parse_eap(const struct parse_data *data,
750 struct wpa_ssid *ssid, int line,
753 int last, errors = 0;
754 char *start, *end, *buf;
755 u8 *methods = NULL, *tmp;
756 size_t num_methods = 0;
763 while (*start != '\0') {
764 while (*start == ' ' || *start == '\t')
769 while (*end != ' ' && *end != '\t' && *end != '\0')
774 methods = realloc(methods, num_methods + 1);
775 if (methods == NULL) {
779 methods[num_methods] = eap_get_type(start);
780 if (methods[num_methods] == EAP_TYPE_NONE) {
781 wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
782 "'%s'", line, start);
783 wpa_printf(MSG_ERROR, "You may need to add support for"
784 " this EAP method during wpa_supplicant\n"
785 "build time configuration.\n"
786 "See README for more information.");
788 } else if (methods[num_methods] == EAP_TYPE_LEAP)
800 methods = realloc(methods, num_methods + 1);
801 if (methods == NULL) {
805 methods[num_methods] = EAP_TYPE_NONE;
808 wpa_hexdump(MSG_MSGDUMP, "eap methods", methods, num_methods);
809 ssid->eap_methods = methods;
810 return errors ? -1 : 0;
814 static char * wpa_config_write_eap(const struct parse_data *data,
815 struct wpa_ssid *ssid)
818 char *buf, *pos, *end;
819 const u8 *eap_methods = ssid->eap_methods;
822 if (eap_methods == NULL)
825 pos = buf = malloc(100);
831 while (*eap_methods != EAP_TYPE_NONE) {
832 name = eap_get_name(*eap_methods);
834 pos += snprintf(pos, end - pos, "%s%s",
835 first ? "" : " ", name);
844 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
845 const char *value, int idx)
847 char *buf, title[20];
849 buf = wpa_config_parse_string(value, len);
851 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
855 if (*len > MAX_WEP_KEY_LEN) {
856 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
861 memcpy(key, buf, *len);
863 snprintf(title, sizeof(title), "wep_key%d", idx);
864 wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
869 static int wpa_config_parse_wep_key0(const struct parse_data *data,
870 struct wpa_ssid *ssid, int line,
873 return wpa_config_parse_wep_key(ssid->wep_key[0],
874 &ssid->wep_key_len[0], line,
879 static int wpa_config_parse_wep_key1(const struct parse_data *data,
880 struct wpa_ssid *ssid, int line,
883 return wpa_config_parse_wep_key(ssid->wep_key[1],
884 &ssid->wep_key_len[1], line,
889 static int wpa_config_parse_wep_key2(const struct parse_data *data,
890 struct wpa_ssid *ssid, int line,
893 return wpa_config_parse_wep_key(ssid->wep_key[2],
894 &ssid->wep_key_len[2], line,
899 static int wpa_config_parse_wep_key3(const struct parse_data *data,
900 struct wpa_ssid *ssid, int line,
903 return wpa_config_parse_wep_key(ssid->wep_key[3],
904 &ssid->wep_key_len[3], line,
909 static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
911 if (ssid->wep_key_len[idx] == 0)
913 return wpa_config_write_string(ssid->wep_key[idx],
914 ssid->wep_key_len[idx]);
918 static char * wpa_config_write_wep_key0(const struct parse_data *data,
919 struct wpa_ssid *ssid)
921 return wpa_config_write_wep_key(ssid, 0);
925 static char * wpa_config_write_wep_key1(const struct parse_data *data,
926 struct wpa_ssid *ssid)
928 return wpa_config_write_wep_key(ssid, 1);
932 static char * wpa_config_write_wep_key2(const struct parse_data *data,
933 struct wpa_ssid *ssid)
935 return wpa_config_write_wep_key(ssid, 2);
939 static char * wpa_config_write_wep_key3(const struct parse_data *data,
940 struct wpa_ssid *ssid)
942 return wpa_config_write_wep_key(ssid, 3);
946 /* Helper macros for network block parser */
948 /* OFFSET: Get offset of a variable within the wpa_ssid structure */
949 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
951 /* STR: Define a string variable for an ASCII string; f = field name */
952 #define STR(f) .name = #f, .parser = wpa_config_parse_str, \
953 .writer = wpa_config_write_str, .param1 = OFFSET(f)
955 /* STR_LEN: Define a string variable with a separate variable for storing the
956 * data length. Unlike STR(), this can be used to store arbitrary binary data
957 * (i.e., even nul termination character). */
958 #define STR_LEN(f) STR(f), .param2 = OFFSET(f ## _len)
960 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
961 * explicitly specified. */
962 #define STR_RANGE(f, min, max) STR_LEN(f), .param3 = (void *) (min), \
963 .param4 = (void *) (max)
966 /* INT: Define an integer variable */
967 #define INT(f) .name = #f, .parser = wpa_config_parse_int, \
968 .writer = wpa_config_write_int, \
969 .param1 = OFFSET(f), .param2 = (void *) 0
971 /* INT: Define an integer variable with allowed value range */
972 #define INT_RANGE(f, min, max) INT(f), .param3 = (void *) (min), \
973 .param4 = (void *) (max)
975 /* FUNC: Define a configuration variable that uses a custom function for
976 * parsing and writing the value. */
977 #define FUNC(f) .name = #f, .parser = wpa_config_parse_ ## f, \
978 .writer = wpa_config_write_ ## f
981 * Table of network configuration variables. This table is used to parse each
982 * network configuration variable, e.g., each line in wpa_supplicant.conf file
983 * that is insider a network block.
985 * This table is generated using the helper macros defined above and with
986 * generous help from the C pre-processor. The field name is stored as a string
987 * into .name and for STR and INT types, the offset of the target buffer within
988 * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
989 * offset to the field containing the length of the configuration variable.
990 * .param3 and .param4 can be used to mark the allowed range (length for STR
991 * and value for INT).
993 * For each configuration line in wpa_supplicant.conf, the parser goes through
994 * this table and select the entry that matches with the field name. The parser
995 * function (.parser) is then called to parse the actual value of the field.
997 * This kind of mechanism makes it easy to add new configuration parameters,
998 * since only one line needs to be added into this table and in struct wpa_ssid
999 * definitions if the new variable is either a string or integer. More complex
1000 * types will need to use their own parser and writer functions.
1002 static const struct parse_data ssid_fields[] = {
1003 { STR_RANGE(ssid, 0, MAX_SSID_LEN) },
1004 { INT_RANGE(scan_ssid, 0, 1) },
1006 { FUNC(psk), .key_data = 1 },
1013 { STR_LEN(identity) },
1014 { STR_LEN(anonymous_identity) },
1015 { STR_RANGE(eappsk, EAP_PSK_LEN, EAP_PSK_LEN), .key_data = 1 },
1017 { STR_LEN(password), .key_data = 1 },
1020 { STR(client_cert) },
1021 { STR(private_key) },
1022 { STR(private_key_passwd), .key_data = 1 },
1024 { STR(subject_match) },
1025 { STR(altsubject_match) },
1028 { STR(client_cert2) },
1029 { STR(private_key2) },
1030 { STR(private_key2_passwd), .key_data = 1 },
1032 { STR(subject_match2) },
1033 { STR(altsubject_match2) },
1037 { STR(pin), .key_data = 1 },
1041 { INT(eapol_flags) },
1042 { FUNC(wep_key0), .key_data = 1 },
1043 { FUNC(wep_key1), .key_data = 1 },
1044 { FUNC(wep_key2), .key_data = 1 },
1045 { FUNC(wep_key3), .key_data = 1 },
1046 { INT(wep_tx_keyidx) },
1048 { INT(eap_workaround) },
1050 { INT_RANGE(mode, 0, 1) },
1051 { INT_RANGE(proactive_key_caching, 0, 1) },
1052 { INT_RANGE(disabled, 0, 1) },
1062 #define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
1066 * wpa_config_add_prio_network - Add a network to priority lists
1067 * @config: Configuration data from wpa_config_read()
1068 * Returns: 0 on success, -1 on failure
1070 * This function is used to add a network block to the priority list of
1071 * networks. This must be called for each network when reading in the full
1072 * configuration. In addition, this can be used indirectly when updating
1073 * priorities by calling wpa_config_update_prio_list().
1075 int wpa_config_add_prio_network(struct wpa_config *config,
1076 struct wpa_ssid *ssid)
1079 struct wpa_ssid *prev, **nlist;
1081 for (prio = 0; prio < config->num_prio; prio++) {
1082 prev = config->pssid[prio];
1083 if (prev->priority == ssid->priority) {
1091 /* First network for this priority - add new priority list */
1092 nlist = realloc(config->pssid,
1093 (config->num_prio + 1) * sizeof(struct wpa_ssid *));
1097 for (prio = 0; prio < config->num_prio; prio++) {
1098 if (nlist[prio]->priority < ssid->priority)
1102 memmove(&nlist[prio + 1], &nlist[prio],
1103 (config->num_prio - prio) * sizeof(struct wpa_ssid *));
1107 config->pssid = nlist;
1114 * wpa_config_update_prio_list - Update network priority list
1115 * @config: Configuration data from wpa_config_read()
1116 * Returns: 0 on success, -1 on failure
1118 * This function is called to update the priority list of networks in the
1119 * configuration when a network is being added or removed. This is also called
1120 * if a priority for a network is changed.
1122 static int wpa_config_update_prio_list(struct wpa_config *config)
1124 struct wpa_ssid *ssid;
1127 free(config->pssid);
1128 config->pssid = NULL;
1129 config->num_prio = 0;
1131 ssid = config->ssid;
1134 if (wpa_config_add_prio_network(config, ssid) < 0)
1144 * wpa_config_free_ssid - Free network/ssid configuration data
1145 * @ssid: Configuration data for the network
1147 * This function frees all resources allocated for the netowkr configuration
1150 void wpa_config_free_ssid(struct wpa_ssid *ssid)
1153 free(ssid->passphrase);
1154 free(ssid->eap_methods);
1155 free(ssid->identity);
1156 free(ssid->anonymous_identity);
1159 free(ssid->password);
1160 free(ssid->ca_cert);
1161 free(ssid->ca_path);
1162 free(ssid->client_cert);
1163 free(ssid->private_key);
1164 free(ssid->private_key_passwd);
1165 free(ssid->dh_file);
1166 free(ssid->subject_match);
1167 free(ssid->altsubject_match);
1168 free(ssid->ca_cert2);
1169 free(ssid->ca_path2);
1170 free(ssid->client_cert2);
1171 free(ssid->private_key2);
1172 free(ssid->private_key2_passwd);
1173 free(ssid->dh_file2);
1174 free(ssid->subject_match2);
1175 free(ssid->altsubject_match2);
1180 free(ssid->engine_id);
1183 free(ssid->pending_req_otp);
1184 free(ssid->pac_file);
1185 free(ssid->new_password);
1191 * wpa_config_free - Free configuration data
1192 * @config: Configuration data from wpa_config_read()
1194 * This function frees all resources allocated for the configuration data by
1195 * wpa_config_read().
1197 void wpa_config_free(struct wpa_config *config)
1199 struct wpa_config_blob *blob, *prevblob;
1200 struct wpa_ssid *ssid, *prev = NULL;
1201 ssid = config->ssid;
1205 wpa_config_free_ssid(prev);
1208 blob = config->blobs;
1213 wpa_config_free_blob(prevblob);
1216 free(config->ctrl_interface);
1217 free(config->opensc_engine_path);
1218 free(config->pkcs11_engine_path);
1219 free(config->pkcs11_module_path);
1220 free(config->driver_param);
1221 free(config->pssid);
1227 * wpa_config_allowed_eap_method - Check whether EAP method is allowed
1228 * @ssid: Pointer to a configuration data
1230 * Returns: 1 = allowed EAP method, 0 = not allowed
1232 int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int method)
1236 if (ssid == NULL || ssid->eap_methods == NULL)
1239 pos = ssid->eap_methods;
1240 while (*pos != EAP_TYPE_NONE) {
1250 * wpa_config_get_network - Get configured network based on id
1251 * @config: Configuration data from wpa_config_read()
1252 * @id: Unique network id to search for
1253 * Returns: Network configuration or %NULL if not found
1255 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
1257 struct wpa_ssid *ssid;
1259 ssid = config->ssid;
1271 * wpa_config_add_network - Add a new network with empty configuration
1272 * @config: Configuration data from wpa_config_read()
1273 * Returns: The new network configuration or %NULL if operation failed
1275 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
1278 struct wpa_ssid *ssid, *last = NULL;
1281 ssid = config->ssid;
1290 ssid = malloc(sizeof(*ssid));
1293 memset(ssid, 0, sizeof(*ssid));
1298 config->ssid = ssid;
1300 wpa_config_update_prio_list(config);
1307 * wpa_config_remove_network - Remove a configured network based on id
1308 * @config: Configuration data from wpa_config_read()
1309 * @id: Unique network id to search for
1310 * Returns: 0 on success, or -1 if the network was not found
1312 int wpa_config_remove_network(struct wpa_config *config, int id)
1314 struct wpa_ssid *ssid, *prev = NULL;
1316 ssid = config->ssid;
1328 prev->next = ssid->next;
1330 config->ssid = ssid->next;
1332 wpa_config_update_prio_list(config);
1333 wpa_config_free_ssid(ssid);
1339 * wpa_config_set_network_defaults - Set network default values
1340 * @ssid: Pointer to a network configuration data
1342 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
1344 ssid->proto = DEFAULT_PROTO;
1345 ssid->pairwise_cipher = DEFAULT_PAIRWISE;
1346 ssid->group_cipher = DEFAULT_GROUP;
1347 ssid->key_mgmt = DEFAULT_KEY_MGMT;
1348 ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
1349 ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
1354 * wpa_config_set - Set a variable in network configuration
1355 * @ssid: Pointer to a network configuration data
1356 * @var: Variable name, e.g., "ssid"
1357 * @value: Variable value
1358 * @line: Line number in configuration file or 0 if not used
1359 * Returns: 0 on success, -1 on failure
1361 * This function can be used to set network configuration variables based on
1362 * both the configuration file and management interface input. The value
1363 * parameter must be in the same format as the text-based configuration file is
1364 * using. For example, strings are using double quotation marks.
1366 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
1371 if (ssid == NULL || var == NULL || value == NULL)
1374 for (i = 0; i < NUM_SSID_FIELDS; i++) {
1375 const struct parse_data *field = &ssid_fields[i];
1376 if (strcmp(var, field->name) != 0)
1379 if (field->parser(field, ssid, line, value)) {
1381 wpa_printf(MSG_ERROR, "Line %d: failed to "
1382 "parse %s '%s'.", line, var, value);
1388 if (i == NUM_SSID_FIELDS) {
1390 wpa_printf(MSG_ERROR, "Line %d: unknown network field "
1391 "'%s'.", line, var);
1401 * wpa_config_get - Get a variable in network configuration
1402 * @ssid: Pointer to a network configuration data
1403 * @var: Variable name, e.g., "ssid"
1404 * Returns: Value of the variable or %NULL on failure
1406 * This function can be used to get network configuration variables. The
1407 * returned value is a copy of the configuration variable in text format, i.e,.
1408 * the same format that the text-based configuration file and wpa_config_set()
1409 * are using for the value. The caller is responsible for freeing the returned
1412 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
1416 if (ssid == NULL || var == NULL)
1419 for (i = 0; i < NUM_SSID_FIELDS; i++) {
1420 const struct parse_data *field = &ssid_fields[i];
1421 if (strcmp(var, field->name) == 0)
1422 return field->writer(field, ssid);
1430 * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
1431 * @ssid: Pointer to a network configuration data
1433 * This function must be called to update WPA PSK when either SSID or the
1434 * passphrase has changed for the network configuration.
1436 void wpa_config_update_psk(struct wpa_ssid *ssid)
1438 pbkdf2_sha1(ssid->passphrase,
1439 (char *) ssid->ssid, ssid->ssid_len, 4096,
1440 ssid->psk, PMK_LEN);
1441 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1442 ssid->psk, PMK_LEN);
1448 * wpa_config_get_blob - Get a named configuration blob
1449 * @config: Configuration data from wpa_config_read()
1450 * @name: Name of the blob
1451 * Returns: Pointer to blob data or %NULL if not found
1453 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
1456 struct wpa_config_blob *blob = config->blobs;
1459 if (strcmp(blob->name, name) == 0)
1468 * wpa_config_set_blob - Set or add a named configuration blob
1469 * @config: Configuration data from wpa_config_read()
1470 * @blob: New value for the blob
1472 * Adds a new configuration blob or replaces the current value of an existing
1475 void wpa_config_set_blob(struct wpa_config *config,
1476 struct wpa_config_blob *blob)
1478 wpa_config_remove_blob(config, blob->name);
1479 blob->next = config->blobs;
1480 config->blobs = blob;
1485 * wpa_config_free_blob - Free blob data
1486 * @blob: Pointer to blob to be freed
1488 void wpa_config_free_blob(struct wpa_config_blob *blob)
1499 * wpa_config_remove_blob - Remove a named configuration blob
1500 * @config: Configuration data from wpa_config_read()
1501 * @name: Name of the blob to remove
1502 * Returns: 0 if blob was removed or -1 if blob was not found
1504 int wpa_config_remove_blob(struct wpa_config *config, const char *name)
1506 struct wpa_config_blob *pos = config->blobs, *prev = NULL;
1509 if (strcmp(pos->name, name) == 0) {
1511 prev->next = pos->next;
1513 config->blobs = pos->next;
1514 wpa_config_free_blob(pos);
1526 * wpa_config_alloc_empty - Allocate an empty configuration
1527 * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
1529 * @driver_param: Driver parameters
1530 * Returns: Pointer to allocated configuration data or %NULL on failure
1532 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
1533 const char *driver_param)
1535 struct wpa_config *config;
1537 config = malloc(sizeof(*config));
1540 memset(config, 0, sizeof(*config));
1541 config->eapol_version = DEFAULT_EAPOL_VERSION;
1542 config->ap_scan = DEFAULT_AP_SCAN;
1543 config->fast_reauth = DEFAULT_FAST_REAUTH;
1546 config->ctrl_interface = strdup(ctrl_interface);
1548 config->driver_param = strdup(driver_param);