]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WNM: Add support for SSID List element matching
authorJouni Malinen <j@w1.fi>
Sun, 16 Dec 2012 19:22:24 +0000 (21:22 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 16 Dec 2012 19:22:24 +0000 (21:22 +0200)
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>

src/ap/beacon.c
src/ap/ieee802_11_shared.c
src/common/ieee802_11_common.c
src/common/ieee802_11_common.h
src/common/ieee802_11_defs.h

index f761bf55bc602f3174f07e4e53c040e168abcd71..4c47c75841c51b49a668ca0b34f7074e6723ee5a 100644 (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");
index 72c127616af19895b7297bf81eaa58908a7bf3ee..7d87379de1ae78c3ca7be75acb7d8a419620a49f 100644 (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)
index d9d3cd05a0a133583b74e84a3ed55e39f18c9f65..98fadda1f90c1b7da6cad3320083379b8e4a3e7e 100644 (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)
index bfc3eb278c097e28b8c40ea14a0822ed06b59de1..55fa49d1f6da655ab493ccc1dc037caa5fb87aa9 100644 (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;
index 484a5b9c48b331d72ad76bade10a0196a9ed1769..1a9ad1a7d2cfd40aa0a9d5703ea6d39d084bb51f 100644 (file)
 #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