From 0a66ce3c49db7425b8cdd253e1ee381073970689 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Dec 2012 21:22:24 +0200 Subject: [PATCH] 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 --- src/ap/beacon.c | 61 +++++++++++++++++++++++++++++----- src/ap/ieee802_11_shared.c | 7 ++++ src/common/ieee802_11_common.c | 4 +++ src/common/ieee802_11_common.h | 4 ++- src/common/ieee802_11_defs.h | 1 + 5 files changed, 67 insertions(+), 10 deletions(-) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index f761bf55b..4c47c7584 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -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 + * Copyright (c) 2008-2012, Jouni Malinen * * 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"); diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 72c127616..7d87379de 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -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) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index d9d3cd05a..98fadda1f 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -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) diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index bfc3eb278..55fa49d1f 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -1,6 +1,6 @@ /* * IEEE 802.11 Common routines - * Copyright (c) 2002-2009, Jouni Malinen + * Copyright (c) 2002-2012, Jouni Malinen * * 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; diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 484a5b9c4..1a9ad1a7d 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -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