3 * Copyright (c) 2010, Jouni Malinen <j@w1.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.
15 #include "utils/includes.h"
17 #include "utils/common.h"
18 #include "common/defs.h"
19 #include "common/ieee802_11_defs.h"
20 #include "common/ieee802_11_common.h"
21 #include "crypto/sha1.h"
25 struct wlantest_bss
* bss_find(struct wlantest
*wt
, const u8
*bssid
)
27 struct wlantest_bss
*bss
;
29 dl_list_for_each(bss
, &wt
->bss
, struct wlantest_bss
, list
) {
30 if (os_memcmp(bss
->bssid
, bssid
, ETH_ALEN
) == 0)
38 struct wlantest_bss
* bss_get(struct wlantest
*wt
, const u8
*bssid
)
40 struct wlantest_bss
*bss
;
43 return NULL
; /* Skip group addressed frames */
45 bss
= bss_find(wt
, bssid
);
49 bss
= os_zalloc(sizeof(*bss
));
52 dl_list_init(&bss
->sta
);
53 dl_list_init(&bss
->pmk
);
54 dl_list_init(&bss
->tdls
);
55 os_memcpy(bss
->bssid
, bssid
, ETH_ALEN
);
56 dl_list_add(&wt
->bss
, &bss
->list
);
57 wpa_printf(MSG_DEBUG
, "Discovered new BSS - " MACSTR
,
63 void pmk_deinit(struct wlantest_pmk
*pmk
)
65 dl_list_del(&pmk
->list
);
70 void bss_deinit(struct wlantest_bss
*bss
)
72 struct wlantest_sta
*sta
, *n
;
73 struct wlantest_pmk
*pmk
, *np
;
74 struct wlantest_tdls
*tdls
, *nt
;
75 dl_list_for_each_safe(sta
, n
, &bss
->sta
, struct wlantest_sta
, list
)
77 dl_list_for_each_safe(pmk
, np
, &bss
->pmk
, struct wlantest_pmk
, list
)
79 dl_list_for_each_safe(tdls
, nt
, &bss
->tdls
, struct wlantest_tdls
, list
)
81 dl_list_del(&bss
->list
);
86 int bss_add_pmk_from_passphrase(struct wlantest_bss
*bss
,
87 const char *passphrase
)
89 struct wlantest_pmk
*pmk
;
91 pmk
= os_zalloc(sizeof(*pmk
));
94 if (pbkdf2_sha1(passphrase
, (char *) bss
->ssid
, bss
->ssid_len
, 4096,
95 pmk
->pmk
, sizeof(pmk
->pmk
)) < 0) {
100 wpa_printf(MSG_INFO
, "Add possible PMK for BSSID " MACSTR
101 " based on passphrase '%s'",
102 MAC2STR(bss
->bssid
), passphrase
);
103 wpa_hexdump(MSG_DEBUG
, "Possible PMK", pmk
->pmk
, sizeof(pmk
->pmk
));
104 dl_list_add(&bss
->pmk
, &pmk
->list
);
110 static void bss_add_pmk(struct wlantest
*wt
, struct wlantest_bss
*bss
)
112 struct wlantest_passphrase
*p
;
114 dl_list_for_each(p
, &wt
->passphrase
, struct wlantest_passphrase
, list
)
116 if (!is_zero_ether_addr(p
->bssid
) &&
117 os_memcmp(p
->bssid
, bss
->bssid
, ETH_ALEN
) != 0)
120 (p
->ssid_len
!= bss
->ssid_len
||
121 os_memcmp(p
->ssid
, bss
->ssid
, p
->ssid_len
) != 0))
124 if (bss_add_pmk_from_passphrase(bss
, p
->passphrase
) < 0)
130 void bss_update(struct wlantest
*wt
, struct wlantest_bss
*bss
,
131 struct ieee802_11_elems
*elems
)
133 struct wpa_ie_data data
;
136 if (bss
->capab_info
!= bss
->prev_capab_info
)
139 if (elems
->ssid
== NULL
|| elems
->ssid_len
> 32) {
140 wpa_printf(MSG_INFO
, "Invalid or missing SSID in a Beacon "
141 "frame for " MACSTR
, MAC2STR(bss
->bssid
));
142 bss
->parse_error_reported
= 1;
146 if (bss
->ssid_len
!= elems
->ssid_len
||
147 os_memcmp(bss
->ssid
, elems
->ssid
, bss
->ssid_len
) != 0) {
148 wpa_printf(MSG_DEBUG
, "Store SSID '%s' for BSSID " MACSTR
,
149 wpa_ssid_txt(elems
->ssid
, elems
->ssid_len
),
150 MAC2STR(bss
->bssid
));
151 os_memcpy(bss
->ssid
, elems
->ssid
, elems
->ssid_len
);
152 bss
->ssid_len
= elems
->ssid_len
;
153 bss_add_pmk(wt
, bss
);
157 if (elems
->rsn_ie
== NULL
) {
159 wpa_printf(MSG_INFO
, "BSS " MACSTR
" - RSN IE removed",
160 MAC2STR(bss
->bssid
));
165 if (bss
->rsnie
[0] == 0 ||
166 os_memcmp(bss
->rsnie
, elems
->rsn_ie
- 2,
167 elems
->rsn_ie_len
+ 2) != 0) {
168 wpa_printf(MSG_INFO
, "BSS " MACSTR
" - RSN IE "
169 "stored", MAC2STR(bss
->bssid
));
170 wpa_hexdump(MSG_DEBUG
, "RSN IE", elems
->rsn_ie
- 2,
171 elems
->rsn_ie_len
+ 2);
174 os_memcpy(bss
->rsnie
, elems
->rsn_ie
- 2,
175 elems
->rsn_ie_len
+ 2);
178 if (elems
->wpa_ie
== NULL
) {
180 wpa_printf(MSG_INFO
, "BSS " MACSTR
" - WPA IE removed",
181 MAC2STR(bss
->bssid
));
186 if (bss
->wpaie
[0] == 0 ||
187 os_memcmp(bss
->wpaie
, elems
->wpa_ie
- 2,
188 elems
->wpa_ie_len
+ 2) != 0) {
189 wpa_printf(MSG_INFO
, "BSS " MACSTR
" - WPA IE "
190 "stored", MAC2STR(bss
->bssid
));
191 wpa_hexdump(MSG_DEBUG
, "WPA IE", elems
->wpa_ie
- 2,
192 elems
->wpa_ie_len
+ 2);
195 os_memcpy(bss
->wpaie
, elems
->wpa_ie
- 2,
196 elems
->wpa_ie_len
+ 2);
202 bss
->prev_capab_info
= bss
->capab_info
;
204 bss
->pairwise_cipher
= 0;
205 bss
->group_cipher
= 0;
208 bss
->mgmt_group_cipher
= 0;
211 if (wpa_parse_wpa_ie_wpa(bss
->wpaie
, 2 + bss
->wpaie
[1], &data
)
213 wpa_printf(MSG_INFO
, "Failed to parse WPA IE from "
214 MACSTR
, MAC2STR(bss
->bssid
));
216 bss
->proto
|= data
.proto
;
217 bss
->pairwise_cipher
|= data
.pairwise_cipher
;
218 bss
->group_cipher
|= data
.group_cipher
;
219 bss
->key_mgmt
|= data
.key_mgmt
;
220 bss
->rsn_capab
= data
.capabilities
;
221 bss
->mgmt_group_cipher
|= data
.mgmt_group_cipher
;
226 if (wpa_parse_wpa_ie_rsn(bss
->rsnie
, 2 + bss
->rsnie
[1], &data
)
228 wpa_printf(MSG_INFO
, "Failed to parse RSN IE from "
229 MACSTR
, MAC2STR(bss
->bssid
));
231 bss
->proto
|= data
.proto
;
232 bss
->pairwise_cipher
|= data
.pairwise_cipher
;
233 bss
->group_cipher
|= data
.group_cipher
;
234 bss
->key_mgmt
|= data
.key_mgmt
;
235 bss
->rsn_capab
= data
.capabilities
;
236 bss
->mgmt_group_cipher
|= data
.mgmt_group_cipher
;
240 if (!(bss
->proto
& WPA_PROTO_RSN
) ||
241 !(bss
->rsn_capab
& WPA_CAPABILITY_MFPC
))
242 bss
->mgmt_group_cipher
= 0;
244 if (!bss
->wpaie
[0] && !bss
->rsnie
[0] &&
245 (bss
->capab_info
& WLAN_CAPABILITY_PRIVACY
))
246 bss
->group_cipher
= WPA_CIPHER_WEP40
;
248 wpa_printf(MSG_INFO
, "BSS " MACSTR
252 "mgmt_group_cipher=%s"
253 "key_mgmt=%s%s%s%s%s%s%s%s"
254 "rsn_capab=%s%s%s%s%s",
256 bss
->proto
== 0 ? "OPEN " : "",
257 bss
->proto
& WPA_PROTO_WPA
? "WPA " : "",
258 bss
->proto
& WPA_PROTO_RSN
? "WPA2 " : "",
259 bss
->pairwise_cipher
== 0 ? "N/A " : "",
260 bss
->pairwise_cipher
& WPA_CIPHER_NONE
? "NONE " : "",
261 bss
->pairwise_cipher
& WPA_CIPHER_TKIP
? "TKIP " : "",
262 bss
->pairwise_cipher
& WPA_CIPHER_CCMP
? "CCMP " : "",
263 bss
->group_cipher
== 0 ? "N/A " : "",
264 bss
->group_cipher
& WPA_CIPHER_NONE
? "NONE " : "",
265 bss
->group_cipher
& WPA_CIPHER_WEP40
? "WEP40 " : "",
266 bss
->group_cipher
& WPA_CIPHER_WEP104
? "WEP104 " : "",
267 bss
->group_cipher
& WPA_CIPHER_TKIP
? "TKIP " : "",
268 bss
->group_cipher
& WPA_CIPHER_CCMP
? "CCMP " : "",
269 bss
->mgmt_group_cipher
& WPA_CIPHER_AES_128_CMAC
? "BIP " :
271 bss
->key_mgmt
== 0 ? "N/A " : "",
272 bss
->key_mgmt
& WPA_KEY_MGMT_IEEE8021X
? "EAP " : "",
273 bss
->key_mgmt
& WPA_KEY_MGMT_PSK
? "PSK " : "",
274 bss
->key_mgmt
& WPA_KEY_MGMT_WPA_NONE
? "WPA-NONE " : "",
275 bss
->key_mgmt
& WPA_KEY_MGMT_FT_IEEE8021X
? "FT-EAP " : "",
276 bss
->key_mgmt
& WPA_KEY_MGMT_FT_PSK
? "FT-PSK " : "",
277 bss
->key_mgmt
& WPA_KEY_MGMT_IEEE8021X_SHA256
?
279 bss
->key_mgmt
& WPA_KEY_MGMT_PSK_SHA256
?
281 bss
->rsn_capab
& WPA_CAPABILITY_PREAUTH
? "PREAUTH " : "",
282 bss
->rsn_capab
& WPA_CAPABILITY_NO_PAIRWISE
?
284 bss
->rsn_capab
& WPA_CAPABILITY_MFPR
? "MFPR " : "",
285 bss
->rsn_capab
& WPA_CAPABILITY_MFPC
? "MFPC " : "",
286 bss
->rsn_capab
& WPA_CAPABILITY_PEERKEY_ENABLED
?
291 void bss_flush(struct wlantest
*wt
)
293 struct wlantest_bss
*bss
, *n
;
294 dl_list_for_each_safe(bss
, n
, &wt
->bss
, struct wlantest_bss
, list
)