Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cffdd30d authored by John W. Linville's avatar John W. Linville
Browse files

[PATCH] mac80211: store SSID in sta_bss_list



Some AP equipment "in the wild" services multiple SSIDs using the
same BSSID.  This patch changes the key of sta_bss_list to include
the SSID as well as the BSSID and the channel so as to prevent one
SSID from eclipsing another SSID with the same BSSID.

Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 65c107ab
Loading
Loading
Loading
Loading
+33 −21
Original line number Original line Diff line number Diff line
@@ -12,7 +12,6 @@
 */
 */


/* TODO:
/* TODO:
 * BSS table: use <BSSID,SSID> as the key to support multi-SSID APs
 * order BSS list by RSSI(?) ("quality of AP")
 * order BSS list by RSSI(?) ("quality of AP")
 * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
 * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
 *    SSID)
 *    SSID)
@@ -61,7 +60,8 @@
static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
				     u8 *ssid, size_t ssid_len);
				     u8 *ssid, size_t ssid_len);
static struct ieee80211_sta_bss *
static struct ieee80211_sta_bss *
ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel);
ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
		     u8 *ssid, u8 ssid_len);
static void ieee80211_rx_bss_put(struct net_device *dev,
static void ieee80211_rx_bss_put(struct net_device *dev,
				 struct ieee80211_sta_bss *bss);
				 struct ieee80211_sta_bss *bss);
static int ieee80211_sta_find_ibss(struct net_device *dev,
static int ieee80211_sta_find_ibss(struct net_device *dev,
@@ -428,7 +428,8 @@ static void ieee80211_set_associated(struct net_device *dev,
			return;
			return;


		bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
		bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
					   local->hw.conf.channel);
					   local->hw.conf.channel,
					   ifsta->ssid, ifsta->ssid_len);
		if (bss) {
		if (bss) {
			if (bss->has_erp_value)
			if (bss->has_erp_value)
				ieee80211_handle_erp_ie(dev, bss->erp_value);
				ieee80211_handle_erp_ie(dev, bss->erp_value);
@@ -575,7 +576,8 @@ static void ieee80211_send_assoc(struct net_device *dev,
		capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
		capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
			WLAN_CAPABILITY_SHORT_PREAMBLE;
			WLAN_CAPABILITY_SHORT_PREAMBLE;
	}
	}
	bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel);
	bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
				   ifsta->ssid, ifsta->ssid_len);
	if (bss) {
	if (bss) {
		if (bss->capability & WLAN_CAPABILITY_PRIVACY)
		if (bss->capability & WLAN_CAPABILITY_PRIVACY)
			capab |= WLAN_CAPABILITY_PRIVACY;
			capab |= WLAN_CAPABILITY_PRIVACY;
@@ -731,7 +733,8 @@ static int ieee80211_privacy_mismatch(struct net_device *dev,
	    ifsta->key_management_enabled)
	    ifsta->key_management_enabled)
		return 0;
		return 0;


	bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel);
	bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
				   ifsta->ssid, ifsta->ssid_len);
	if (!bss)
	if (!bss)
		return 0;
		return 0;


@@ -1245,7 +1248,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
	if (elems.erp_info && elems.erp_info_len >= 1) {
	if (elems.erp_info && elems.erp_info_len >= 1) {
		struct ieee80211_sta_bss *bss
		struct ieee80211_sta_bss *bss
			= ieee80211_rx_bss_get(dev, ifsta->bssid,
			= ieee80211_rx_bss_get(dev, ifsta->bssid,
					       local->hw.conf.channel);
					       local->hw.conf.channel,
					       ifsta->ssid, ifsta->ssid_len);
		if (bss) {
		if (bss) {
			bss->erp_value = elems.erp_info[0];
			bss->erp_value = elems.erp_info[0];
			bss->has_erp_value = 1;
			bss->has_erp_value = 1;
@@ -1276,7 +1280,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
			return;
			return;
		}
		}
		bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
		bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
					   local->hw.conf.channel);
					   local->hw.conf.channel,
					   ifsta->ssid, ifsta->ssid_len);
		if (bss) {
		if (bss) {
			sta->last_rssi = bss->rssi;
			sta->last_rssi = bss->rssi;
			sta->last_signal = bss->signal;
			sta->last_signal = bss->signal;
@@ -1352,7 +1357,8 @@ static void __ieee80211_rx_bss_hash_del(struct net_device *dev,




static struct ieee80211_sta_bss *
static struct ieee80211_sta_bss *
ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel)
ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel,
		     u8 *ssid, u8 ssid_len)
{
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_sta_bss *bss;
	struct ieee80211_sta_bss *bss;
@@ -1364,6 +1370,10 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel)
	atomic_inc(&bss->users);
	atomic_inc(&bss->users);
	memcpy(bss->bssid, bssid, ETH_ALEN);
	memcpy(bss->bssid, bssid, ETH_ALEN);
	bss->channel = channel;
	bss->channel = channel;
	if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
		memcpy(bss->ssid, ssid, ssid_len);
		bss->ssid_len = ssid_len;
	}


	spin_lock_bh(&local->sta_bss_lock);
	spin_lock_bh(&local->sta_bss_lock);
	/* TODO: order by RSSI? */
	/* TODO: order by RSSI? */
@@ -1375,7 +1385,8 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel)




static struct ieee80211_sta_bss *
static struct ieee80211_sta_bss *
ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel)
ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
		     u8 *ssid, u8 ssid_len)
{
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_sta_bss *bss;
	struct ieee80211_sta_bss *bss;
@@ -1383,8 +1394,10 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel)
	spin_lock_bh(&local->sta_bss_lock);
	spin_lock_bh(&local->sta_bss_lock);
	bss = local->sta_bss_hash[STA_HASH(bssid)];
	bss = local->sta_bss_hash[STA_HASH(bssid)];
	while (bss) {
	while (bss) {
		if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
		if (!memcmp(bss->bssid, bssid, ETH_ALEN) &&
		    bss->channel == channel) {
		    bss->channel == channel &&
		    bss->ssid_len == ssid_len &&
		    (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
			atomic_inc(&bss->users);
			atomic_inc(&bss->users);
			break;
			break;
		}
		}
@@ -1552,9 +1565,11 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
	else
	else
		channel = rx_status->channel;
		channel = rx_status->channel;


	bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel);
	bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel,
				   elems.ssid, elems.ssid_len);
	if (!bss) {
	if (!bss) {
		bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel);
		bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel,
					   elems.ssid, elems.ssid_len);
		if (!bss)
		if (!bss)
			return;
			return;
	} else {
	} else {
@@ -1580,10 +1595,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,


	bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
	bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
	bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
	bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
	if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
		memcpy(bss->ssid, elems.ssid, elems.ssid_len);
		bss->ssid_len = elems.ssid_len;
	}


	bss->supp_rates_len = 0;
	bss->supp_rates_len = 0;
	if (elems.supp_rates) {
	if (elems.supp_rates) {
@@ -2381,7 +2392,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
{
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_sta_bss *bss;
	struct ieee80211_sta_bss *bss;
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_hw_mode *mode;
	struct ieee80211_hw_mode *mode;
	u8 bssid[ETH_ALEN], *pos;
	u8 bssid[ETH_ALEN], *pos;
	int i;
	int i;
@@ -2404,11 +2415,11 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
	printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
	printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
	       dev->name, print_mac(mac, bssid));
	       dev->name, print_mac(mac, bssid));


	bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel);
	bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel,
				   sdata->u.sta.ssid, sdata->u.sta.ssid_len);
	if (!bss)
	if (!bss)
		return -ENOMEM;
		return -ENOMEM;


	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	mode = local->oper_hw_mode;
	mode = local->oper_hw_mode;


	if (local->hw.conf.beacon_int == 0)
	if (local->hw.conf.beacon_int == 0)
@@ -2474,7 +2485,8 @@ static int ieee80211_sta_find_ibss(struct net_device *dev,
	       "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
	       "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
	if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
	if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
	    (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel))) {
	    (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel,
					ifsta->ssid, ifsta->ssid_len))) {
		printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
		printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
		       " based on configured SSID\n",
		       " based on configured SSID\n",
		       dev->name, print_mac(mac, bssid));
		       dev->name, print_mac(mac, bssid));