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 = strrchr(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'.",
101 data->key_data ? "[KEY DATA REMOVED]" : value);
107 if (data->key_data) {
108 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
109 (u8 *) *dst, res_len);
111 wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
112 (u8 *) *dst, res_len);
115 if (data->param3 && res_len < (size_t) data->param3) {
116 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
117 "min_len=%ld)", line, data->name,
118 (unsigned long) res_len, (long) data->param3);
124 if (data->param4 && res_len > (size_t) data->param4) {
125 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
126 "max_len=%ld)", line, data->name,
127 (unsigned long) res_len, (long) data->param4);
137 static int is_hex(const u8 *data, size_t len)
141 for (i = 0; i < len; i++) {
142 if (data[i] < 32 || data[i] >= 127)
149 static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
152 char *buf, *pos, *end;
154 pos = buf = malloc(len + 3);
158 pos += snprintf(pos, end - pos, "\"");
159 for (i = 0; i < len; i++)
160 pos += snprintf(pos, end - pos, "%c", value[i]);
161 pos += snprintf(pos, end - pos, "\"");
167 static char * wpa_config_write_string_hex(const u8 *value, size_t len)
170 char *buf, *pos, *end;
172 pos = buf = malloc(2 * len + 1);
175 memset(buf, 0, 2 * len + 1);
176 end = buf + 2 * len + 1;
177 for (i = 0; i < len; i++)
178 pos += snprintf(pos, end - pos, "%02x", value[i]);
184 static char * wpa_config_write_string(const u8 *value, size_t len)
189 if (is_hex(value, len))
190 return wpa_config_write_string_hex(value, len);
192 return wpa_config_write_string_ascii(value, len);
196 static char * wpa_config_write_str(const struct parse_data *data,
197 struct wpa_ssid *ssid)
202 src = (char **) (((u8 *) ssid) + (long) data->param1);
207 len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
211 return wpa_config_write_string((const u8 *) *src, len);
215 static int wpa_config_parse_int(const struct parse_data *data,
216 struct wpa_ssid *ssid,
217 int line, const char *value)
221 dst = (int *) (((u8 *) ssid) + (long) data->param1);
223 wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
225 if (data->param3 && *dst < (long) data->param3) {
226 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
227 "min_value=%ld)", line, data->name, *dst,
228 (long) data->param3);
229 *dst = (long) data->param3;
233 if (data->param4 && *dst > (long) data->param4) {
234 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
235 "max_value=%ld)", line, data->name, *dst,
236 (long) data->param4);
237 *dst = (long) data->param4;
245 static char * wpa_config_write_int(const struct parse_data *data,
246 struct wpa_ssid *ssid)
251 src = (int *) (((u8 *) ssid) + (long) data->param1);
256 snprintf(value, 20, "%d", *src);
261 static int wpa_config_parse_bssid(const struct parse_data *data,
262 struct wpa_ssid *ssid, int line,
265 if (hwaddr_aton(value, ssid->bssid)) {
266 wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
271 wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
276 static char * wpa_config_write_bssid(const struct parse_data *data,
277 struct wpa_ssid *ssid)
281 if (!ssid->bssid_set)
287 snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
292 static int wpa_config_parse_psk(const struct parse_data *data,
293 struct wpa_ssid *ssid, int line,
301 pos = strrchr(value, '"');
306 if (len < 8 || len > 63) {
307 wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
308 "length %lu (expected: 8..63) '%s'.",
309 line, (unsigned long) len, value);
312 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
314 ssid->passphrase = malloc(len + 1);
315 if (ssid->passphrase == NULL)
317 memcpy(ssid->passphrase, value, len);
318 ssid->passphrase[len] = '\0';
322 if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
323 value[PMK_LEN * 2] != '\0') {
324 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
329 wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
334 static char * wpa_config_write_psk(const struct parse_data *data,
335 struct wpa_ssid *ssid)
337 if (ssid->passphrase)
338 return wpa_config_write_string_ascii(
339 (const u8 *) ssid->passphrase,
340 strlen(ssid->passphrase));
343 return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
349 static int wpa_config_parse_proto(const struct parse_data *data,
350 struct wpa_ssid *ssid, int line,
353 int val = 0, last, errors = 0;
354 char *start, *end, *buf;
361 while (*start != '\0') {
362 while (*start == ' ' || *start == '\t')
367 while (*end != ' ' && *end != '\t' && *end != '\0')
371 if (strcmp(start, "WPA") == 0)
372 val |= WPA_PROTO_WPA;
373 else if (strcmp(start, "RSN") == 0 ||
374 strcmp(start, "WPA2") == 0)
375 val |= WPA_PROTO_RSN;
377 wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
389 wpa_printf(MSG_ERROR,
390 "Line %d: no proto values configured.", line);
394 wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
396 return errors ? -1 : 0;
400 static char * wpa_config_write_proto(const struct parse_data *data,
401 struct wpa_ssid *ssid)
404 char *buf, *pos, *end;
406 pos = buf = malloc(10);
412 if (ssid->proto & WPA_PROTO_WPA) {
413 pos += snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
417 if (ssid->proto & WPA_PROTO_RSN) {
418 pos += snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
426 static int wpa_config_parse_key_mgmt(const struct parse_data *data,
427 struct wpa_ssid *ssid, int line,
430 int val = 0, last, errors = 0;
431 char *start, *end, *buf;
438 while (*start != '\0') {
439 while (*start == ' ' || *start == '\t')
444 while (*end != ' ' && *end != '\t' && *end != '\0')
448 if (strcmp(start, "WPA-PSK") == 0)
449 val |= WPA_KEY_MGMT_PSK;
450 else if (strcmp(start, "WPA-EAP") == 0)
451 val |= WPA_KEY_MGMT_IEEE8021X;
452 else if (strcmp(start, "IEEE8021X") == 0)
453 val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
454 else if (strcmp(start, "NONE") == 0)
455 val |= WPA_KEY_MGMT_NONE;
456 else if (strcmp(start, "WPA-NONE") == 0)
457 val |= WPA_KEY_MGMT_WPA_NONE;
459 wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
471 wpa_printf(MSG_ERROR,
472 "Line %d: no key_mgmt values configured.", line);
476 wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
477 ssid->key_mgmt = val;
478 return errors ? -1 : 0;
482 static char * wpa_config_write_key_mgmt(const struct parse_data *data,
483 struct wpa_ssid *ssid)
486 char *buf, *pos, *end;
488 pos = buf = malloc(50);
494 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
495 pos += snprintf(pos, end - pos, "%sWPA-PSK", first ? "" : " ");
499 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
500 pos += snprintf(pos, end - pos, "%sWPA-EAP", first ? "" : " ");
504 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
505 pos += snprintf(pos, end - pos, "%sIEEE8021X",
510 if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
511 pos += snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
515 if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
516 pos += snprintf(pos, end - pos, "%sWPA-NONE",
525 static int wpa_config_parse_cipher(int line, const char *value)
528 char *start, *end, *buf;
535 while (*start != '\0') {
536 while (*start == ' ' || *start == '\t')
541 while (*end != ' ' && *end != '\t' && *end != '\0')
545 if (strcmp(start, "CCMP") == 0)
546 val |= WPA_CIPHER_CCMP;
547 else if (strcmp(start, "TKIP") == 0)
548 val |= WPA_CIPHER_TKIP;
549 else if (strcmp(start, "WEP104") == 0)
550 val |= WPA_CIPHER_WEP104;
551 else if (strcmp(start, "WEP40") == 0)
552 val |= WPA_CIPHER_WEP40;
553 else if (strcmp(start, "NONE") == 0)
554 val |= WPA_CIPHER_NONE;
556 wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
569 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
577 static char * wpa_config_write_cipher(int cipher)
580 char *buf, *pos, *end;
582 pos = buf = malloc(50);
588 if (cipher & WPA_CIPHER_CCMP) {
589 pos += snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
593 if (cipher & WPA_CIPHER_TKIP) {
594 pos += snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
598 if (cipher & WPA_CIPHER_WEP104) {
599 pos += snprintf(pos, end - pos, "%sWEP104", first ? "" : " ");
603 if (cipher & WPA_CIPHER_WEP40) {
604 pos += snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
608 if (cipher & WPA_CIPHER_NONE) {
609 pos += snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
617 static int wpa_config_parse_pairwise(const struct parse_data *data,
618 struct wpa_ssid *ssid, int line,
622 val = wpa_config_parse_cipher(line, value);
625 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) {
626 wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
627 "(0x%x).", line, val);
631 wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
632 ssid->pairwise_cipher = val;
637 static char * wpa_config_write_pairwise(const struct parse_data *data,
638 struct wpa_ssid *ssid)
640 return wpa_config_write_cipher(ssid->pairwise_cipher);
644 static int wpa_config_parse_group(const struct parse_data *data,
645 struct wpa_ssid *ssid, int line,
649 val = wpa_config_parse_cipher(line, value);
652 if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 |
654 wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
655 "(0x%x).", line, val);
659 wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
660 ssid->group_cipher = val;
665 static char * wpa_config_write_group(const struct parse_data *data,
666 struct wpa_ssid *ssid)
668 return wpa_config_write_cipher(ssid->group_cipher);
672 static int wpa_config_parse_auth_alg(const struct parse_data *data,
673 struct wpa_ssid *ssid, int line,
676 int val = 0, last, errors = 0;
677 char *start, *end, *buf;
684 while (*start != '\0') {
685 while (*start == ' ' || *start == '\t')
690 while (*end != ' ' && *end != '\t' && *end != '\0')
694 if (strcmp(start, "OPEN") == 0)
695 val |= WPA_AUTH_ALG_OPEN;
696 else if (strcmp(start, "SHARED") == 0)
697 val |= WPA_AUTH_ALG_SHARED;
698 else if (strcmp(start, "LEAP") == 0)
699 val |= WPA_AUTH_ALG_LEAP;
701 wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
713 wpa_printf(MSG_ERROR,
714 "Line %d: no auth_alg values configured.", line);
718 wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
719 ssid->auth_alg = val;
720 return errors ? -1 : 0;
724 static char * wpa_config_write_auth_alg(const struct parse_data *data,
725 struct wpa_ssid *ssid)
728 char *buf, *pos, *end;
730 pos = buf = malloc(30);
736 if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
737 pos += snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
741 if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
742 pos += snprintf(pos, end - pos, "%sSHARED", first ? "" : " ");
746 if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
747 pos += snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
755 static int wpa_config_parse_eap(const struct parse_data *data,
756 struct wpa_ssid *ssid, int line,
759 int last, errors = 0;
760 char *start, *end, *buf;
761 u8 *methods = NULL, *tmp;
762 size_t num_methods = 0;
769 while (*start != '\0') {
770 while (*start == ' ' || *start == '\t')
775 while (*end != ' ' && *end != '\t' && *end != '\0')
780 methods = realloc(methods, num_methods + 1);
781 if (methods == NULL) {
786 methods[num_methods] = eap_get_type(start);
787 if (methods[num_methods] == EAP_TYPE_NONE) {
788 wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
789 "'%s'", line, start);
790 wpa_printf(MSG_ERROR, "You may need to add support for"
791 " this EAP method during wpa_supplicant\n"
792 "build time configuration.\n"
793 "See README for more information.");
795 } else if (methods[num_methods] == EAP_TYPE_LEAP)
807 methods = realloc(methods, num_methods + 1);
808 if (methods == NULL) {
812 methods[num_methods] = EAP_TYPE_NONE;
815 wpa_hexdump(MSG_MSGDUMP, "eap methods", methods, num_methods);
816 ssid->eap_methods = methods;
817 return errors ? -1 : 0;
821 static char * wpa_config_write_eap(const struct parse_data *data,
822 struct wpa_ssid *ssid)
825 char *buf, *pos, *end;
826 const u8 *eap_methods = ssid->eap_methods;
829 if (eap_methods == NULL)
832 pos = buf = malloc(100);
838 while (*eap_methods != EAP_TYPE_NONE) {
839 name = eap_get_name(*eap_methods);
841 pos += snprintf(pos, end - pos, "%s%s",
842 first ? "" : " ", name);
851 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
852 const char *value, int idx)
854 char *buf, title[20];
856 buf = wpa_config_parse_string(value, len);
858 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
862 if (*len > MAX_WEP_KEY_LEN) {
863 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
868 memcpy(key, buf, *len);
870 snprintf(title, sizeof(title), "wep_key%d", idx);
871 wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
876 static int wpa_config_parse_wep_key0(const struct parse_data *data,
877 struct wpa_ssid *ssid, int line,
880 return wpa_config_parse_wep_key(ssid->wep_key[0],
881 &ssid->wep_key_len[0], line,
886 static int wpa_config_parse_wep_key1(const struct parse_data *data,
887 struct wpa_ssid *ssid, int line,
890 return wpa_config_parse_wep_key(ssid->wep_key[1],
891 &ssid->wep_key_len[1], line,
896 static int wpa_config_parse_wep_key2(const struct parse_data *data,
897 struct wpa_ssid *ssid, int line,
900 return wpa_config_parse_wep_key(ssid->wep_key[2],
901 &ssid->wep_key_len[2], line,
906 static int wpa_config_parse_wep_key3(const struct parse_data *data,
907 struct wpa_ssid *ssid, int line,
910 return wpa_config_parse_wep_key(ssid->wep_key[3],
911 &ssid->wep_key_len[3], line,
916 static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
918 if (ssid->wep_key_len[idx] == 0)
920 return wpa_config_write_string(ssid->wep_key[idx],
921 ssid->wep_key_len[idx]);
925 static char * wpa_config_write_wep_key0(const struct parse_data *data,
926 struct wpa_ssid *ssid)
928 return wpa_config_write_wep_key(ssid, 0);
932 static char * wpa_config_write_wep_key1(const struct parse_data *data,
933 struct wpa_ssid *ssid)
935 return wpa_config_write_wep_key(ssid, 1);
939 static char * wpa_config_write_wep_key2(const struct parse_data *data,
940 struct wpa_ssid *ssid)
942 return wpa_config_write_wep_key(ssid, 2);
946 static char * wpa_config_write_wep_key3(const struct parse_data *data,
947 struct wpa_ssid *ssid)
949 return wpa_config_write_wep_key(ssid, 3);
953 /* Helper macros for network block parser */
955 /* OFFSET: Get offset of a variable within the wpa_ssid structure */
956 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
958 /* STR: Define a string variable for an ASCII string; f = field name */
959 #define STR(f) .name = #f, .parser = wpa_config_parse_str, \
960 .writer = wpa_config_write_str, .param1 = OFFSET(f)
962 /* STR_LEN: Define a string variable with a separate variable for storing the
963 * data length. Unlike STR(), this can be used to store arbitrary binary data
964 * (i.e., even nul termination character). */
965 #define STR_LEN(f) STR(f), .param2 = OFFSET(f ## _len)
967 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
968 * explicitly specified. */
969 #define STR_RANGE(f, min, max) STR_LEN(f), .param3 = (void *) (min), \
970 .param4 = (void *) (max)
973 /* INT: Define an integer variable */
974 #define INT(f) .name = #f, .parser = wpa_config_parse_int, \
975 .writer = wpa_config_write_int, \
976 .param1 = OFFSET(f), .param2 = (void *) 0
978 /* INT: Define an integer variable with allowed value range */
979 #define INT_RANGE(f, min, max) INT(f), .param3 = (void *) (min), \
980 .param4 = (void *) (max)
982 /* FUNC: Define a configuration variable that uses a custom function for
983 * parsing and writing the value. */
984 #define FUNC(f) .name = #f, .parser = wpa_config_parse_ ## f, \
985 .writer = wpa_config_write_ ## f
988 * Table of network configuration variables. This table is used to parse each
989 * network configuration variable, e.g., each line in wpa_supplicant.conf file
990 * that is inside a network block.
992 * This table is generated using the helper macros defined above and with
993 * generous help from the C pre-processor. The field name is stored as a string
994 * into .name and for STR and INT types, the offset of the target buffer within
995 * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
996 * offset to the field containing the length of the configuration variable.
997 * .param3 and .param4 can be used to mark the allowed range (length for STR
998 * and value for INT).
1000 * For each configuration line in wpa_supplicant.conf, the parser goes through
1001 * this table and select the entry that matches with the field name. The parser
1002 * function (.parser) is then called to parse the actual value of the field.
1004 * This kind of mechanism makes it easy to add new configuration parameters,
1005 * since only one line needs to be added into this table and into the
1006 * struct wpa_ssid definition if the new variable is either a string or
1007 * integer. More complex types will need to use their own parser and writer
1010 static const struct parse_data ssid_fields[] = {
1011 { STR_RANGE(ssid, 0, MAX_SSID_LEN) },
1012 { INT_RANGE(scan_ssid, 0, 1) },
1014 { FUNC(psk), .key_data = 1 },
1021 { STR_LEN(identity) },
1022 { STR_LEN(anonymous_identity) },
1023 { STR_RANGE(eappsk, EAP_PSK_LEN, EAP_PSK_LEN), .key_data = 1 },
1025 { STR_LEN(password), .key_data = 1 },
1028 { STR(client_cert) },
1029 { STR(private_key) },
1030 { STR(private_key_passwd), .key_data = 1 },
1032 { STR(subject_match) },
1033 { STR(altsubject_match) },
1036 { STR(client_cert2) },
1037 { STR(private_key2) },
1038 { STR(private_key2_passwd), .key_data = 1 },
1040 { STR(subject_match2) },
1041 { STR(altsubject_match2) },
1045 { STR(pin), .key_data = 1 },
1049 { INT(eapol_flags) },
1050 { FUNC(wep_key0), .key_data = 1 },
1051 { FUNC(wep_key1), .key_data = 1 },
1052 { FUNC(wep_key2), .key_data = 1 },
1053 { FUNC(wep_key3), .key_data = 1 },
1054 { INT(wep_tx_keyidx) },
1056 { INT(eap_workaround) },
1058 { INT_RANGE(mode, 0, 1) },
1059 { INT_RANGE(proactive_key_caching, 0, 1) },
1060 { INT_RANGE(disabled, 0, 1) },
1070 #define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
1074 * wpa_config_add_prio_network - Add a network to priority lists
1075 * @config: Configuration data from wpa_config_read()
1076 * @ssid: Pointer to the network configuration to be added to the list
1077 * Returns: 0 on success, -1 on failure
1079 * This function is used to add a network block to the priority list of
1080 * networks. This must be called for each network when reading in the full
1081 * configuration. In addition, this can be used indirectly when updating
1082 * priorities by calling wpa_config_update_prio_list().
1084 int wpa_config_add_prio_network(struct wpa_config *config,
1085 struct wpa_ssid *ssid)
1088 struct wpa_ssid *prev, **nlist;
1091 * Add to an existing priority list if one is available for the
1092 * configured priority level for this network.
1094 for (prio = 0; prio < config->num_prio; prio++) {
1095 prev = config->pssid[prio];
1096 if (prev->priority == ssid->priority) {
1104 /* First network for this priority - add a new priority list */
1105 nlist = realloc(config->pssid,
1106 (config->num_prio + 1) * sizeof(struct wpa_ssid *));
1110 for (prio = 0; prio < config->num_prio; prio++) {
1111 if (nlist[prio]->priority < ssid->priority)
1115 memmove(&nlist[prio + 1], &nlist[prio],
1116 (config->num_prio - prio) * sizeof(struct wpa_ssid *));
1120 config->pssid = nlist;
1127 * wpa_config_update_prio_list - Update network priority list
1128 * @config: Configuration data from wpa_config_read()
1129 * Returns: 0 on success, -1 on failure
1131 * This function is called to update the priority list of networks in the
1132 * configuration when a network is being added or removed. This is also called
1133 * if a priority for a network is changed.
1135 static int wpa_config_update_prio_list(struct wpa_config *config)
1137 struct wpa_ssid *ssid;
1140 free(config->pssid);
1141 config->pssid = NULL;
1142 config->num_prio = 0;
1144 ssid = config->ssid;
1147 if (wpa_config_add_prio_network(config, ssid) < 0)
1157 * wpa_config_free_ssid - Free network/ssid configuration data
1158 * @ssid: Configuration data for the network
1160 * This function frees all resources allocated for the network configuration
1163 void wpa_config_free_ssid(struct wpa_ssid *ssid)
1166 free(ssid->passphrase);
1167 free(ssid->eap_methods);
1168 free(ssid->identity);
1169 free(ssid->anonymous_identity);
1172 free(ssid->password);
1173 free(ssid->ca_cert);
1174 free(ssid->ca_path);
1175 free(ssid->client_cert);
1176 free(ssid->private_key);
1177 free(ssid->private_key_passwd);
1178 free(ssid->dh_file);
1179 free(ssid->subject_match);
1180 free(ssid->altsubject_match);
1181 free(ssid->ca_cert2);
1182 free(ssid->ca_path2);
1183 free(ssid->client_cert2);
1184 free(ssid->private_key2);
1185 free(ssid->private_key2_passwd);
1186 free(ssid->dh_file2);
1187 free(ssid->subject_match2);
1188 free(ssid->altsubject_match2);
1193 free(ssid->engine_id);
1196 free(ssid->pending_req_otp);
1197 free(ssid->pac_file);
1198 free(ssid->new_password);
1204 * wpa_config_free - Free configuration data
1205 * @config: Configuration data from wpa_config_read()
1207 * This function frees all resources allocated for the configuration data by
1208 * wpa_config_read().
1210 void wpa_config_free(struct wpa_config *config)
1212 struct wpa_config_blob *blob, *prevblob;
1213 struct wpa_ssid *ssid, *prev = NULL;
1214 ssid = config->ssid;
1218 wpa_config_free_ssid(prev);
1221 blob = config->blobs;
1226 wpa_config_free_blob(prevblob);
1229 free(config->ctrl_interface);
1230 free(config->opensc_engine_path);
1231 free(config->pkcs11_engine_path);
1232 free(config->pkcs11_module_path);
1233 free(config->driver_param);
1234 free(config->pssid);
1240 * wpa_config_allowed_eap_method - Check whether EAP method is allowed
1241 * @ssid: Pointer to configuration data
1243 * Returns: 1 = allowed EAP method, 0 = not allowed
1245 int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int method)
1249 if (ssid == NULL || ssid->eap_methods == NULL)
1252 pos = ssid->eap_methods;
1253 while (*pos != EAP_TYPE_NONE) {
1263 * wpa_config_get_network - Get configured network based on id
1264 * @config: Configuration data from wpa_config_read()
1265 * @id: Unique network id to search for
1266 * Returns: Network configuration or %NULL if not found
1268 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
1270 struct wpa_ssid *ssid;
1272 ssid = config->ssid;
1284 * wpa_config_add_network - Add a new network with empty configuration
1285 * @config: Configuration data from wpa_config_read()
1286 * Returns: The new network configuration or %NULL if operation failed
1288 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
1291 struct wpa_ssid *ssid, *last = NULL;
1294 ssid = config->ssid;
1303 ssid = malloc(sizeof(*ssid));
1306 memset(ssid, 0, sizeof(*ssid));
1311 config->ssid = ssid;
1313 wpa_config_update_prio_list(config);
1320 * wpa_config_remove_network - Remove a configured network based on id
1321 * @config: Configuration data from wpa_config_read()
1322 * @id: Unique network id to search for
1323 * Returns: 0 on success, or -1 if the network was not found
1325 int wpa_config_remove_network(struct wpa_config *config, int id)
1327 struct wpa_ssid *ssid, *prev = NULL;
1329 ssid = config->ssid;
1341 prev->next = ssid->next;
1343 config->ssid = ssid->next;
1345 wpa_config_update_prio_list(config);
1346 wpa_config_free_ssid(ssid);
1352 * wpa_config_set_network_defaults - Set network default values
1353 * @ssid: Pointer to network configuration data
1355 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
1357 ssid->proto = DEFAULT_PROTO;
1358 ssid->pairwise_cipher = DEFAULT_PAIRWISE;
1359 ssid->group_cipher = DEFAULT_GROUP;
1360 ssid->key_mgmt = DEFAULT_KEY_MGMT;
1361 ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
1362 ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
1367 * wpa_config_set - Set a variable in network configuration
1368 * @ssid: Pointer to network configuration data
1369 * @var: Variable name, e.g., "ssid"
1370 * @value: Variable value
1371 * @line: Line number in configuration file or 0 if not used
1372 * Returns: 0 on success, -1 on failure
1374 * This function can be used to set network configuration variables based on
1375 * both the configuration file and management interface input. The value
1376 * parameter must be in the same format as the text-based configuration file is
1377 * using. For example, strings are using double quotation marks.
1379 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
1384 if (ssid == NULL || var == NULL || value == NULL)
1387 for (i = 0; i < NUM_SSID_FIELDS; i++) {
1388 const struct parse_data *field = &ssid_fields[i];
1389 if (strcmp(var, field->name) != 0)
1392 if (field->parser(field, ssid, line, value)) {
1394 wpa_printf(MSG_ERROR, "Line %d: failed to "
1395 "parse %s '%s'.", line, var, value);
1401 if (i == NUM_SSID_FIELDS) {
1403 wpa_printf(MSG_ERROR, "Line %d: unknown network field "
1404 "'%s'.", line, var);
1414 * wpa_config_get - Get a variable in network configuration
1415 * @ssid: Pointer to network configuration data
1416 * @var: Variable name, e.g., "ssid"
1417 * Returns: Value of the variable or %NULL on failure
1419 * This function can be used to get network configuration variables. The
1420 * returned value is a copy of the configuration variable in text format, i.e,.
1421 * the same format that the text-based configuration file and wpa_config_set()
1422 * are using for the value. The caller is responsible for freeing the returned
1425 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
1429 if (ssid == NULL || var == NULL)
1432 for (i = 0; i < NUM_SSID_FIELDS; i++) {
1433 const struct parse_data *field = &ssid_fields[i];
1434 if (strcmp(var, field->name) == 0)
1435 return field->writer(field, ssid);
1443 * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
1444 * @ssid: Pointer to network configuration data
1446 * This function must be called to update WPA PSK when either SSID or the
1447 * passphrase has changed for the network configuration.
1449 void wpa_config_update_psk(struct wpa_ssid *ssid)
1451 pbkdf2_sha1(ssid->passphrase,
1452 (char *) ssid->ssid, ssid->ssid_len, 4096,
1453 ssid->psk, PMK_LEN);
1454 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1455 ssid->psk, PMK_LEN);
1461 * wpa_config_get_blob - Get a named configuration blob
1462 * @config: Configuration data from wpa_config_read()
1463 * @name: Name of the blob
1464 * Returns: Pointer to blob data or %NULL if not found
1466 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
1469 struct wpa_config_blob *blob = config->blobs;
1472 if (strcmp(blob->name, name) == 0)
1481 * wpa_config_set_blob - Set or add a named configuration blob
1482 * @config: Configuration data from wpa_config_read()
1483 * @blob: New value for the blob
1485 * Adds a new configuration blob or replaces the current value of an existing
1488 void wpa_config_set_blob(struct wpa_config *config,
1489 struct wpa_config_blob *blob)
1491 wpa_config_remove_blob(config, blob->name);
1492 blob->next = config->blobs;
1493 config->blobs = blob;
1498 * wpa_config_free_blob - Free blob data
1499 * @blob: Pointer to blob to be freed
1501 void wpa_config_free_blob(struct wpa_config_blob *blob)
1512 * wpa_config_remove_blob - Remove a named configuration blob
1513 * @config: Configuration data from wpa_config_read()
1514 * @name: Name of the blob to remove
1515 * Returns: 0 if blob was removed or -1 if blob was not found
1517 int wpa_config_remove_blob(struct wpa_config *config, const char *name)
1519 struct wpa_config_blob *pos = config->blobs, *prev = NULL;
1522 if (strcmp(pos->name, name) == 0) {
1524 prev->next = pos->next;
1526 config->blobs = pos->next;
1527 wpa_config_free_blob(pos);
1539 * wpa_config_alloc_empty - Allocate an empty configuration
1540 * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
1542 * @driver_param: Driver parameters
1543 * Returns: Pointer to allocated configuration data or %NULL on failure
1545 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
1546 const char *driver_param)
1548 struct wpa_config *config;
1550 config = malloc(sizeof(*config));
1553 memset(config, 0, sizeof(*config));
1554 config->eapol_version = DEFAULT_EAPOL_VERSION;
1555 config->ap_scan = DEFAULT_AP_SCAN;
1556 config->fast_reauth = DEFAULT_FAST_REAUTH;
1559 config->ctrl_interface = strdup(ctrl_interface);
1561 config->driver_param = strdup(driver_param);