WNM: Add support for SSID List element matching

This allows Probe Request frame processing to compare the configured
SSID to the SSID List element in addition to the SSID element.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2012-12-16 21:22:24 +02:00
parent b93c8509cc
commit 0a66ce3c49
5 changed files with 67 additions and 10 deletions

View file

@ -2,7 +2,7 @@
* hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
* Copyright (c) 2002-2004, Instant802 Networks, Inc.
* Copyright (c) 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -310,6 +310,46 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
}
enum ssid_match_result {
NO_SSID_MATCH,
EXACT_SSID_MATCH,
WILDCARD_SSID_MATCH
};
static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
const u8 *ssid, size_t ssid_len,
const u8 *ssid_list,
size_t ssid_list_len)
{
const u8 *pos, *end;
int wildcard = 0;
if (ssid_len == 0)
wildcard = 1;
if (ssid_len == hapd->conf->ssid.ssid_len &&
os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
return EXACT_SSID_MATCH;
if (ssid_list == NULL)
return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
pos = ssid_list;
end = ssid_list + ssid_list_len;
while (pos + 1 <= end) {
if (pos + 2 + pos[1] > end)
break;
if (pos[1] == 0)
wildcard = 1;
if (pos[1] == hapd->conf->ssid.ssid_len &&
os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
return EXACT_SSID_MATCH;
pos += 2 + pos[1];
}
return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
}
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len,
int ssi_signal)
@ -321,6 +361,7 @@ void handle_probe_req(struct hostapd_data *hapd,
struct sta_info *sta = NULL;
size_t i, resp_len;
int noack;
enum ssid_match_result res;
ie = mgmt->u.probe_req.variable;
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
@ -376,7 +417,8 @@ void handle_probe_req(struct hostapd_data *hapd,
}
#endif /* CONFIG_P2P */
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) {
if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
elems.ssid_list_len == 0) {
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
"broadcast SSID ignored", MAC2STR(mgmt->sa));
return;
@ -394,10 +436,9 @@ void handle_probe_req(struct hostapd_data *hapd,
}
#endif /* CONFIG_P2P */
if (elems.ssid_len == 0 ||
(elems.ssid_len == hapd->conf->ssid.ssid_len &&
os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) ==
0)) {
res = ssid_match(hapd, elems.ssid, elems.ssid_len,
elems.ssid_list, elems.ssid_list_len);
if (res != NO_SSID_MATCH) {
if (sta)
sta->ssid_probe = &hapd->conf->ssid;
} else {
@ -406,9 +447,10 @@ void handle_probe_req(struct hostapd_data *hapd,
ieee802_11_print_ssid(ssid_txt, elems.ssid,
elems.ssid_len);
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
" for foreign SSID '%s' (DA " MACSTR ")",
" for foreign SSID '%s' (DA " MACSTR ")%s",
MAC2STR(mgmt->sa), ssid_txt,
MAC2STR(mgmt->da));
MAC2STR(mgmt->da),
elems.ssid_list ? " (SSID list)" : "");
}
return;
}
@ -455,7 +497,8 @@ void handle_probe_req(struct hostapd_data *hapd,
* If this is a broadcast probe request, apply no ack policy to avoid
* excessive retries.
*/
noack = !!(elems.ssid_len == 0 && is_broadcast_ether_addr(mgmt->da));
noack = !!(res == WILDCARD_SSID_MATCH &&
is_broadcast_ether_addr(mgmt->da));
if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0)
perror("handle_probe_req: send");

View file

@ -177,6 +177,10 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
len = 3;
if (len < 7 && hapd->conf->ssid.utf8_ssid)
len = 7;
#ifdef CONFIG_WNM
if (len < 4)
len = 4;
#endif /* CONFIG_WNM */
if (len == 0)
return eid;
@ -193,6 +197,9 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
if (len < 4)
return pos;
*pos = 0x00;
#ifdef CONFIG_WNM
*pos |= 0x02; /* Bit 25 - SSID List */
#endif /* CONFIG_WNM */
if (hapd->conf->time_advertisement == 2)
*pos |= 0x08; /* Bit 27 - UTC TSF Offset */
if (hapd->conf->interworking)

View file

@ -284,6 +284,10 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
break;
elems->bss_max_idle_period = pos;
break;
case WLAN_EID_SSID_LIST:
elems->ssid_list = pos;
elems->ssid_list_len = elen;
break;
default:
unknown++;
if (!show_errors)

View file

@ -1,6 +1,6 @@
/*
* IEEE 802.11 Common routines
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -43,6 +43,7 @@ struct ieee802_11_elems {
const u8 *hs20;
const u8 *ext_capab;
const u8 *bss_max_idle_period;
const u8 *ssid_list;
u8 ssid_len;
u8 supp_rates_len;
@ -74,6 +75,7 @@ struct ieee802_11_elems {
u8 interworking_len;
u8 hs20_len;
u8 ext_capab_len;
u8 ssid_list_len;
};
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;

View file

@ -232,6 +232,7 @@
#define WLAN_EID_20_40_BSS_INTOLERANT 73
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
#define WLAN_EID_MMIE 76
#define WLAN_EID_SSID_LIST 84
#define WLAN_EID_BSS_MAX_IDLE_PERIOD 90
#define WLAN_EID_TFS_REQ 91
#define WLAN_EID_TFS_RESP 92