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