Commit fe3d2c3f authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

mac80211: split managed/ibss code a little more

It appears that you can completely mess up mac80211 in IBSS
mode by sending it a disassoc or deauth: it'll stop queues
and do a lot more but not ever do anything again. Fix this
by not handling all those frames in IBSS mode,
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a71800f3
...@@ -808,9 +808,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ...@@ -808,9 +808,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
bss_info_changed |= BSS_CHANGED_ASSOC; bss_info_changed |= BSS_CHANGED_ASSOC;
ifsta->flags |= IEEE80211_STA_ASSOCIATED; ifsta->flags |= IEEE80211_STA_ASSOCIATED;
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return;
bss = ieee80211_rx_bss_get(local, ifsta->bssid, bss = ieee80211_rx_bss_get(local, ifsta->bssid,
conf->channel->center_freq, conf->channel->center_freq,
ifsta->ssid, ifsta->ssid_len); ifsta->ssid, ifsta->ssid_len);
...@@ -1169,44 +1166,52 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, ...@@ -1169,44 +1166,52 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
elems.challenge_len + 2, 1); elems.challenge_len + 2, 1);
} }
static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_sta *ifsta, struct ieee80211_if_sta *ifsta,
struct ieee80211_mgmt *mgmt, struct ieee80211_mgmt *mgmt,
size_t len) size_t len)
{ {
u16 auth_alg, auth_transaction, status_code; u16 auth_alg, auth_transaction, status_code;
if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE &&
sdata->vif.type != NL80211_IFTYPE_ADHOC)
return;
if (len < 24 + 6) if (len < 24 + 6)
return; return;
if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0)
return;
if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
return;
auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
status_code = le16_to_cpu(mgmt->u.auth.status_code); status_code = le16_to_cpu(mgmt->u.auth.status_code);
if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
/* /*
* IEEE 802.11 standard does not require authentication in IBSS * IEEE 802.11 standard does not require authentication in IBSS
* networks and most implementations do not seem to use it. * networks and most implementations do not seem to use it.
* However, try to reply to authentication attempts if someone * However, try to reply to authentication attempts if someone
* has actually implemented this. * has actually implemented this.
*/ */
if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1)
return;
ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0); ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0);
}
static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_sta *ifsta,
struct ieee80211_mgmt *mgmt,
size_t len)
{
u16 auth_alg, auth_transaction, status_code;
if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE)
return; return;
}
if (len < 24 + 6)
return;
if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0)
return;
if (memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
return;
auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
status_code = le16_to_cpu(mgmt->u.auth.status_code);
if (auth_alg != ifsta->auth_alg || if (auth_alg != ifsta->auth_alg ||
auth_transaction != ifsta->auth_transaction) auth_transaction != ifsta->auth_transaction)
...@@ -1762,47 +1767,56 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ...@@ -1762,47 +1767,56 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
/* was just updated in ieee80211_bss_info_update */ /* was just updated in ieee80211_bss_info_update */
beacon_timestamp = bss->cbss.tsf; beacon_timestamp = bss->cbss.tsf;
/* if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
* In STA mode, the remaining parameters should not be overridden goto put_bss;
* by beacons because they're not necessarily accurate there.
*/
if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
bss->last_probe_resp && beacon) {
ieee80211_rx_bss_put(local, bss);
return;
}
/* check if we need to merge IBSS */ /* check if we need to merge IBSS */
if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon &&
(!(sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)) && /* merge only on beacons (???) */
bss->cbss.capability & WLAN_CAPABILITY_IBSS && if (!beacon)
bss->cbss.channel == local->oper_channel && goto put_bss;
elems->ssid_len == sdata->u.sta.ssid_len &&
/* we use a fixed BSSID */
if (sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)
goto put_bss;
/* not an IBSS */
if (!(bss->cbss.capability & WLAN_CAPABILITY_IBSS))
goto put_bss;
/* different channel */
if (bss->cbss.channel != local->oper_channel)
goto put_bss;
/* different SSID */
if (elems->ssid_len != sdata->u.sta.ssid_len ||
memcmp(elems->ssid, sdata->u.sta.ssid, memcmp(elems->ssid, sdata->u.sta.ssid,
sdata->u.sta.ssid_len) == 0) { sdata->u.sta.ssid_len))
goto put_bss;
if (rx_status->flag & RX_FLAG_TSFT) { if (rx_status->flag & RX_FLAG_TSFT) {
/* in order for correct IBSS merging we need mactime /*
* For correct IBSS merging we need mactime; since mactime is
* defined as the time the first data symbol of the frame hits
* the PHY, and the timestamp of the beacon is defined as "the
* time that the data symbol containing the first bit of the
* timestamp is transmitted to the PHY plus the transmitting
* STA's delays through its local PHY from the MAC-PHY
* interface to its interface with the WM" (802.11 11.1.2)
* - equals the time this bit arrives at the receiver - we have
* to take into account the offset between the two.
* *
* since mactime is defined as the time the first data * E.g. at 1 MBit that means mactime is 192 usec earlier
* symbol of the frame hits the PHY, and the timestamp
* of the beacon is defined as "the time that the data
* symbol containing the first bit of the timestamp is
* transmitted to the PHY plus the transmitting STA’s
* delays through its local PHY from the MAC-PHY
* interface to its interface with the WM"
* (802.11 11.1.2) - equals the time this bit arrives at
* the receiver - we have to take into account the
* offset between the two.
* e.g: at 1 MBit that means mactime is 192 usec earlier
* (=24 bytes * 8 usecs/byte) than the beacon timestamp. * (=24 bytes * 8 usecs/byte) than the beacon timestamp.
*/ */
int rate; int rate;
if (rx_status->flag & RX_FLAG_HT) {
if (rx_status->flag & RX_FLAG_HT)
rate = 65; /* TODO: HT rates */ rate = 65; /* TODO: HT rates */
} else { else
rate = local->hw.wiphy->bands[band]-> rate = local->hw.wiphy->bands[band]->
bitrates[rx_status->rate_idx].bitrate; bitrates[rx_status->rate_idx].bitrate;
}
rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
} else if (local && local->ops && local->ops->get_tsf) } else if (local && local->ops && local->ops->get_tsf)
/* second best option: get current TSF */ /* second best option: get current TSF */
...@@ -1810,6 +1824,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ...@@ -1810,6 +1824,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
else else
/* can't merge without knowing the TSF */ /* can't merge without knowing the TSF */
rx_timestamp = -1LLU; rx_timestamp = -1LLU;
#ifdef CONFIG_MAC80211_IBSS_DEBUG #ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "RX beacon SA=%pM BSSID=" printk(KERN_DEBUG "RX beacon SA=%pM BSSID="
"%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n", "%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
...@@ -1818,7 +1833,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ...@@ -1818,7 +1833,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
(unsigned long long)beacon_timestamp, (unsigned long long)beacon_timestamp,
(unsigned long long)(rx_timestamp - beacon_timestamp), (unsigned long long)(rx_timestamp - beacon_timestamp),
jiffies); jiffies);
#endif /* CONFIG_MAC80211_IBSS_DEBUG */ #endif
if (beacon_timestamp > rx_timestamp) { if (beacon_timestamp > rx_timestamp) {
#ifdef CONFIG_MAC80211_IBSS_DEBUG #ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG "%s: beacon TSF higher than " printk(KERN_DEBUG "%s: beacon TSF higher than "
...@@ -1828,8 +1844,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ...@@ -1828,8 +1844,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss);
ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
} }
}
put_bss:
ieee80211_rx_bss_put(local, bss); ieee80211_rx_bss_put(local, bss);
} }
...@@ -1993,8 +2009,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, ...@@ -1993,8 +2009,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *resp; struct ieee80211_mgmt *resp;
u8 *pos, *end; u8 *pos, *end;
if (sdata->vif.type != NL80211_IFTYPE_ADHOC || if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED ||
ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED ||
len < 24 + 2 || !ifsta->probe_resp) len < 24 + 2 || !ifsta->probe_resp)
return; return;
...@@ -2098,32 +2113,55 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ...@@ -2098,32 +2113,55 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
mgmt = (struct ieee80211_mgmt *) skb->data; mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control); fc = le16_to_cpu(mgmt->frame_control);
if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
switch (fc & IEEE80211_FCTL_STYPE) { switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_PROBE_REQ: case IEEE80211_STYPE_PROBE_REQ:
ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len); ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt,
skb->len);
break; break;
case IEEE80211_STYPE_PROBE_RESP: case IEEE80211_STYPE_PROBE_RESP:
ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len,
rx_status);
break; break;
case IEEE80211_STYPE_BEACON: case IEEE80211_STYPE_BEACON:
ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
rx_status);
break;
case IEEE80211_STYPE_AUTH:
ieee80211_rx_mgmt_auth_ibss(sdata, ifsta, mgmt,
skb->len);
break;
}
} else { /* NL80211_IFTYPE_STATION */
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_PROBE_RESP:
ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len,
rx_status);
break;
case IEEE80211_STYPE_BEACON:
ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
rx_status);
break; break;
case IEEE80211_STYPE_AUTH: case IEEE80211_STYPE_AUTH:
ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len); ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len);
break; break;
case IEEE80211_STYPE_ASSOC_RESP: case IEEE80211_STYPE_ASSOC_RESP:
ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0); ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt,
skb->len, 0);
break; break;
case IEEE80211_STYPE_REASSOC_RESP: case IEEE80211_STYPE_REASSOC_RESP:
ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1); ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt,
skb->len, 1);
break; break;
case IEEE80211_STYPE_DEAUTH: case IEEE80211_STYPE_DEAUTH:
ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len); ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len);
break; break;
case IEEE80211_STYPE_DISASSOC: case IEEE80211_STYPE_DISASSOC:
ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt,
skb->len);
break; break;
} }
}
kfree_skb(skb); kfree_skb(skb);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment