]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - src/ap/beacon.c
WNM: Add support for SSID List element matching
[thirdparty/hostap.git] / src / ap / beacon.c
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");