wlantest: Add flush command for dropping all BSS data
[mech_eap.git] / wlantest / bss.c
1 /*
2  * BSS list
3  * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
4  *
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.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "utils/includes.h"
16
17 #include "utils/common.h"
18 #include "common/defs.h"
19 #include "common/ieee802_11_common.h"
20 #include "crypto/sha1.h"
21 #include "wlantest.h"
22
23
24 struct wlantest_bss * bss_get(struct wlantest *wt, const u8 *bssid)
25 {
26         struct wlantest_bss *bss;
27
28         if (bssid[0] & 0x01)
29                 return NULL; /* Skip group addressed frames */
30
31         dl_list_for_each(bss, &wt->bss, struct wlantest_bss, list) {
32                 if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
33                         return bss;
34         }
35
36         bss = os_zalloc(sizeof(*bss));
37         if (bss == NULL)
38                 return NULL;
39         dl_list_init(&bss->sta);
40         dl_list_init(&bss->pmk);
41         os_memcpy(bss->bssid, bssid, ETH_ALEN);
42         dl_list_add(&wt->bss, &bss->list);
43         wpa_printf(MSG_DEBUG, "Discovered new BSS - " MACSTR,
44                    MAC2STR(bss->bssid));
45         return bss;
46 }
47
48
49 void pmk_deinit(struct wlantest_pmk *pmk)
50 {
51         dl_list_del(&pmk->list);
52         os_free(pmk);
53 }
54
55
56 void bss_deinit(struct wlantest_bss *bss)
57 {
58         struct wlantest_sta *sta, *n;
59         struct wlantest_pmk *pmk, *np;
60         dl_list_for_each_safe(sta, n, &bss->sta, struct wlantest_sta, list)
61                 sta_deinit(sta);
62         dl_list_for_each_safe(pmk, np, &bss->pmk, struct wlantest_pmk, list)
63                 pmk_deinit(pmk);
64         dl_list_del(&bss->list);
65         os_free(bss);
66 }
67
68
69 static void bss_add_pmk(struct wlantest *wt, struct wlantest_bss *bss)
70 {
71         struct wlantest_passphrase *p;
72         struct wlantest_pmk *pmk;
73
74         dl_list_for_each(p, &wt->passphrase, struct wlantest_passphrase, list)
75         {
76                 if (!is_zero_ether_addr(p->bssid) &&
77                     os_memcmp(p->bssid, bss->bssid, ETH_ALEN) != 0)
78                         continue;
79                 if (p->ssid_len &&
80                     (p->ssid_len != bss->ssid_len ||
81                      os_memcmp(p->ssid, bss->ssid, p->ssid_len) != 0))
82                         continue;
83
84                 pmk = os_zalloc(sizeof(*pmk));
85                 if (pmk == NULL)
86                         break;
87                 if (pbkdf2_sha1(p->passphrase, (char *) bss->ssid,
88                                 bss->ssid_len, 4096,
89                                 pmk->pmk, sizeof(pmk->pmk)) < 0) {
90                         os_free(pmk);
91                         continue;
92                 }
93
94                 wpa_printf(MSG_INFO, "Add possible PMK for BSSID " MACSTR
95                            " based on passphrase '%s'",
96                            MAC2STR(bss->bssid), p->passphrase);
97                 wpa_hexdump(MSG_DEBUG, "Possible PMK",
98                             pmk->pmk, sizeof(pmk->pmk));
99                 dl_list_add(&bss->pmk, &pmk->list);
100         }
101 }
102
103
104 void bss_update(struct wlantest *wt, struct wlantest_bss *bss,
105                 struct ieee802_11_elems *elems)
106 {
107         struct wpa_ie_data data;
108         int update = 0;
109
110         if (elems->ssid == NULL || elems->ssid_len > 32) {
111                 wpa_printf(MSG_INFO, "Invalid or missing SSID in a Beacon "
112                            "frame for " MACSTR, MAC2STR(bss->bssid));
113                 bss->parse_error_reported = 1;
114                 return;
115         }
116
117         if (bss->ssid_len != elems->ssid_len ||
118             os_memcmp(bss->ssid, elems->ssid, bss->ssid_len) != 0) {
119                 wpa_printf(MSG_DEBUG, "Store SSID '%s' for BSSID " MACSTR,
120                            wpa_ssid_txt(elems->ssid, elems->ssid_len),
121                            MAC2STR(bss->bssid));
122                 os_memcpy(bss->ssid, elems->ssid, elems->ssid_len);
123                 bss->ssid_len = elems->ssid_len;
124                 bss_add_pmk(wt, bss);
125         }
126
127
128         if (elems->rsn_ie == NULL) {
129                 if (bss->rsnie[0]) {
130                         wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE removed",
131                                    MAC2STR(bss->bssid));
132                         bss->rsnie[0] = 0;
133                         update = 1;
134                 }
135         } else {
136                 if (bss->rsnie[0] == 0 ||
137                     os_memcmp(bss->rsnie, elems->rsn_ie - 2,
138                               elems->rsn_ie_len + 2) != 0) {
139                         wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE "
140                                    "stored", MAC2STR(bss->bssid));
141                         wpa_hexdump(MSG_DEBUG, "RSN IE", elems->rsn_ie - 2,
142                                     elems->rsn_ie_len + 2);
143                         update = 1;
144                 }
145                 os_memcpy(bss->rsnie, elems->rsn_ie - 2,
146                           elems->rsn_ie_len + 2);
147         }
148
149         if (elems->wpa_ie == NULL) {
150                 if (bss->wpaie[0]) {
151                         wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE removed",
152                                    MAC2STR(bss->bssid));
153                         bss->wpaie[0] = 0;
154                         update = 1;
155                 }
156         } else {
157                 if (bss->wpaie[0] == 0 ||
158                     os_memcmp(bss->wpaie, elems->wpa_ie - 2,
159                               elems->wpa_ie_len + 2) != 0) {
160                         wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE "
161                                    "stored", MAC2STR(bss->bssid));
162                         wpa_hexdump(MSG_DEBUG, "WPA IE", elems->wpa_ie - 2,
163                                     elems->wpa_ie_len + 2);
164                         update = 1;
165                 }
166                 os_memcpy(bss->wpaie, elems->wpa_ie - 2,
167                           elems->wpa_ie_len + 2);
168         }
169
170         if (!update)
171                 return;
172
173         bss->proto = 0;
174         bss->pairwise_cipher = 0;
175         bss->group_cipher = 0;
176         bss->key_mgmt = 0;
177         bss->rsn_capab = 0;
178         bss->mgmt_group_cipher = 0;
179
180         if (bss->wpaie[0]) {
181                 if (wpa_parse_wpa_ie_wpa(bss->wpaie, 2 + bss->wpaie[1], &data)
182                     < 0) {
183                         wpa_printf(MSG_INFO, "Failed to parse WPA IE from "
184                                    MACSTR, MAC2STR(bss->bssid));
185                 } else {
186                         bss->proto |= data.proto;
187                         bss->pairwise_cipher |= data.pairwise_cipher;
188                         bss->group_cipher |= data.group_cipher;
189                         bss->key_mgmt |= data.key_mgmt;
190                         bss->rsn_capab = data.capabilities;
191                         bss->mgmt_group_cipher |= data.mgmt_group_cipher;
192                 }
193         }
194
195         if (bss->rsnie[0]) {
196                 if (wpa_parse_wpa_ie_rsn(bss->rsnie, 2 + bss->rsnie[1], &data)
197                     < 0) {
198                         wpa_printf(MSG_INFO, "Failed to parse RSN IE from "
199                                    MACSTR, MAC2STR(bss->bssid));
200                 } else {
201                         bss->proto |= data.proto;
202                         bss->pairwise_cipher |= data.pairwise_cipher;
203                         bss->group_cipher |= data.group_cipher;
204                         bss->key_mgmt |= data.key_mgmt;
205                         bss->rsn_capab = data.capabilities;
206                         bss->mgmt_group_cipher |= data.mgmt_group_cipher;
207                 }
208         }
209
210         if (!(bss->proto & WPA_PROTO_RSN) ||
211             !(bss->rsn_capab & WPA_CAPABILITY_MFPC))
212                 bss->mgmt_group_cipher = 0;
213
214         wpa_printf(MSG_INFO, "BSS " MACSTR
215                    " proto=%s%s%s"
216                    "pairwise=%s%s%s%s"
217                    "group=%s%s%s%s%s%s"
218                    "mgmt_group_cipher=%s"
219                    "key_mgmt=%s%s%s%s%s%s%s%s"
220                    "rsn_capab=%s%s%s%s%s",
221                    MAC2STR(bss->bssid),
222                    bss->proto == 0 ? "OPEN " : "",
223                    bss->proto & WPA_PROTO_WPA ? "WPA " : "",
224                    bss->proto & WPA_PROTO_RSN ? "WPA2 " : "",
225                    bss->pairwise_cipher == 0 ? "N/A " : "",
226                    bss->pairwise_cipher & WPA_CIPHER_NONE ? "NONE " : "",
227                    bss->pairwise_cipher & WPA_CIPHER_TKIP ? "TKIP " : "",
228                    bss->pairwise_cipher & WPA_CIPHER_CCMP ? "CCMP " : "",
229                    bss->group_cipher == 0 ? "N/A " : "",
230                    bss->group_cipher & WPA_CIPHER_NONE ? "NONE " : "",
231                    bss->group_cipher & WPA_CIPHER_WEP40 ? "WEP40 " : "",
232                    bss->group_cipher & WPA_CIPHER_WEP104 ? "WEP104 " : "",
233                    bss->group_cipher & WPA_CIPHER_TKIP ? "TKIP " : "",
234                    bss->group_cipher & WPA_CIPHER_CCMP ? "CCMP " : "",
235                    bss->mgmt_group_cipher & WPA_CIPHER_AES_128_CMAC ? "BIP " :
236                    "N/A ",
237                    bss->key_mgmt == 0 ? "N/A " : "",
238                    bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X ? "EAP " : "",
239                    bss->key_mgmt & WPA_KEY_MGMT_PSK ? "PSK " : "",
240                    bss->key_mgmt & WPA_KEY_MGMT_WPA_NONE ? "WPA-NONE " : "",
241                    bss->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X ? "FT-EAP " : "",
242                    bss->key_mgmt & WPA_KEY_MGMT_FT_PSK ? "FT-PSK " : "",
243                    bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256 ?
244                    "EAP-SHA256 " : "",
245                    bss->key_mgmt & WPA_KEY_MGMT_PSK_SHA256 ?
246                    "PSK-SHA256 " : "",
247                    bss->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "",
248                    bss->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ?
249                    "NO_PAIRWISE " : "",
250                    bss->rsn_capab & WPA_CAPABILITY_MFPR ? "MFPR " : "",
251                    bss->rsn_capab & WPA_CAPABILITY_MFPC ? "MFPC " : "",
252                    bss->rsn_capab & WPA_CAPABILITY_PEERKEY_ENABLED ?
253                    "PEERKEY " : "");
254 }
255
256
257 void bss_flush(struct wlantest *wt)
258 {
259         struct wlantest_bss *bss, *n;
260         dl_list_for_each_safe(bss, n, &wt->bss, struct wlantest_bss, list)
261                 bss_deinit(bss);
262 }