[PATCH 4/4] implement secondary SSID capability

Stefan Tomanek stefan.tomanek
Sat Apr 25 08:37:48 PDT 2015


This change enables the definition of secondary SSID strings attached to the
same BSS; clients actively requesting those will be able to associate with the
BSS using the alternative names.

Config example:

interface=wlan1
ssid=Path-e-tec
secondary_ssid=Path-Way
secondary_ssid=E-Tec
hw_mode=g
channel=1

So even after the (fictional) companies Path-Way and E-Tec completed their
merger and renamed their networks, legacy devices can still connect to the old
network names (as long as they employ active scanning, since currently no
beacons are generated for the secondary SSIDs).

Signed-off-by: Stefan Tomanek <stefan.tomanek at wertarbyte.de>
---
 hostapd/config_file.c | 18 ++++++++++++++++++
 src/ap/ap_config.h    | 10 ++++++++++
 src/ap/beacon.c       | 33 ++++++++++++++++++++++++++++++++-
 src/ap/ieee802_11.c   | 20 +++++++++++++++++---
 4 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index e83d125..597ef84 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -1993,6 +1993,24 @@ static int hostapd_config_fill(struct hostapd_config *conf,
 		os_free(str);
 	} else if (os_strcmp(buf, "utf8_ssid") == 0) {
 		bss->ssid.utf8_ssid = atoi(pos) > 0;
+	} else if (os_strcmp(buf, "secondary_ssid") == 0) {
+		struct hostapd_ssid_str *sec;
+		if (bss->secondary_ssid_count >= MAX_BSS_SECONDARY_SSID_COUNT) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: count of secondary ssids exceeded",
+				   line);
+			return 1;
+		}
+		sec = &bss->secondary_ssid[bss->secondary_ssid_count];
+		sec->ssid_len = os_strlen(pos);
+		if (sec->ssid_len > SSID_MAX_LEN ||
+		    sec->ssid_len < 1) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
+				   line, pos);
+			return 1;
+		}
+		os_memcpy(sec->ssid, pos, sec->ssid_len);
+		bss->secondary_ssid_count++;
 	} else if (os_strcmp(buf, "catchall") == 0) {
 		bss->ssid.catchall = atoi(pos) > 0;
 	} else if (os_strcmp(buf, "macaddr_acl") == 0) {
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index b7d4c6a..9f59282 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -77,6 +77,11 @@ typedef enum hostap_security_policy {
 	SECURITY_OSEN = 5
 } secpolicy;
 
+struct hostapd_ssid_str {
+	u8 ssid[SSID_MAX_LEN];
+	size_t ssid_len;
+};
+
 struct hostapd_ssid {
 	u8 ssid[SSID_MAX_LEN];
 	size_t ssid_len;
@@ -212,6 +217,8 @@ struct hostapd_nai_realm_data {
 	} eap_method[MAX_NAI_EAP_METHODS];
 };
 
+#define MAX_BSS_SECONDARY_SSID_COUNT 8
+
 /**
  * struct hostapd_bss_config - Per-BSS configuration
  */
@@ -255,6 +262,9 @@ struct hostapd_bss_config {
 
 	struct hostapd_ssid ssid;
 
+	int secondary_ssid_count;
+	struct hostapd_ssid_str secondary_ssid[MAX_BSS_SECONDARY_SSID_COUNT];
+
 	char *eap_req_id_text; /* optional displayable message sent with
 				* EAP Request-Identity */
 	size_t eap_req_id_text_len;
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index d49716b..56f9dbf 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -504,6 +504,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 enum ssid_match_result {
 	NO_SSID_MATCH,
 	EXACT_SSID_MATCH,
+	SECONDARY_SSID_MATCH,
 	CATCHALL_SSID_MATCH,
 	WILDCARD_SSID_MATCH
 };
@@ -514,6 +515,7 @@ static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
 					 size_t ssid_list_len)
 {
 	const u8 *pos, *end;
+	size_t i;
 	int wildcard = 0;
 
 	if (ssid_len == 0)
@@ -522,6 +524,13 @@ static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
 	    os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
 		return EXACT_SSID_MATCH;
 
+	for (i = 0; i < hapd->conf->secondary_ssid_count; i++) {
+		struct hostapd_ssid_str *s = &hapd->conf->secondary_ssid[i];
+		if (ssid_len == s->ssid_len &&
+		    os_memcmp(ssid, s->ssid, ssid_len) == 0)
+			return SECONDARY_SSID_MATCH;
+	}
+
 	if (ssid_list == NULL)
 		return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
 
@@ -535,6 +544,13 @@ static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
 		if (pos[1] == hapd->conf->ssid.ssid_len &&
 		    os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
 			return EXACT_SSID_MATCH;
+		for (i = 0; i < hapd->conf->secondary_ssid_count; i++) {
+			struct hostapd_ssid_str *s = &hapd->conf->secondary_ssid[i];
+			if (pos[1] == s->ssid_len &&
+			    os_memcmp(pos + 2, s->ssid, pos[1]) == 0)
+				return SECONDARY_SSID_MATCH;
+		}
+
 		pos += 2 + pos[1];
 	}
 
@@ -666,6 +682,16 @@ void handle_probe_req(struct hostapd_data *hapd,
 			 elems.ssid_list, elems.ssid_list_len);
 
 	/*
+	 * The client is requesting one of our secondary
+	 * SSID strings, so we just play along and use the
+	 * supplied values.
+	 */
+	if (res == SECONDARY_SSID_MATCH) {
+		ssid = elems.ssid;
+		ssid_len = elems.ssid_len;
+	}
+
+	/*
 	 * Process the probe request if "catchall" is set and no other match
 	 * is found in this or any other BSS.
 	 */
@@ -687,7 +713,12 @@ void handle_probe_req(struct hostapd_data *hapd,
 		if (sta) {
 			hostapd_free_cloned_ssid(sta->ssid_probe);
 			sta->ssid_probe = NULL;
-			if (res == CATCHALL_SSID_MATCH) {
+			if (res == CATCHALL_SSID_MATCH || res == SECONDARY_SSID_MATCH) {
+				/*
+				 * if the client isn't using the default SSID, we
+				 * create a temporary (and client specific) configuration
+				 * using the default settings as a template
+				 */
 				sta->ssid_probe = hostapd_clone_twin_ssid(hapd->conf, ssid, ssid_len);
 			} else {
 				sta->ssid_probe = &hapd->conf->ssid;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 76a3119..0bee923 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1179,6 +1179,18 @@ static int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
 	return 0;
 }
 
+static u8 check_secondary_ssid(struct hostapd_data *hapd,
+		      const u8 *ssid_ie, size_t ssid_ie_len)
+{
+	size_t i;
+	for (i = 0; i < hapd->conf->secondary_ssid_count; i++) {
+		struct hostapd_ssid_str *s = &hapd->conf->secondary_ssid[i];
+		if (ssid_ie_len == s->ssid_len &&
+		    os_memcmp(ssid_ie, s->ssid, ssid_ie_len) == 0)
+			return 1;
+	}
+	return 0;
+}
 
 static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta,
 		      const u8 *ssid_ie, size_t ssid_ie_len)
@@ -1191,11 +1203,13 @@ static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta,
 		return WLAN_STATUS_SUCCESS;
 	}
 
-	if (hapd->conf->ssid.catchall) {
+	if (hapd->conf->ssid.catchall ||
+	    check_secondary_ssid(hapd, ssid_ie, ssid_ie_len)) {
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_INFO,
-			       "Station associating with catchall network, requested SSID "
-			       "'%s'", wpa_ssid_txt(ssid_ie, ssid_ie_len));
+			       "Station associating with catchall/secondary network,"
+			       "requested SSID '%s'",
+			       wpa_ssid_txt(ssid_ie, ssid_ie_len));
 		sta->ssid = hostapd_clone_twin_ssid(hapd->conf, ssid_ie, ssid_ie_len);
 		if (sta->ssid == NULL)
 			return WLAN_STATUS_UNSPECIFIED_FAILURE;
-- 
2.1.4



More information about the Hostap mailing list