2009-02-09 22:05:10

by Johannes Berg

[permalink] [raw]
Subject: [PATCH] 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,=20

Signed-off-by: Johannes Berg <[email protected]>
---
net/mac80211/mlme.c | 250 +++++++++++++++++++++++++++++--------------=
---------
1 file changed, 142 insertions(+), 108 deletions(-)

--- wireless-testing.orig/net/mac80211/mlme.c 2009-02-09 21:49:46.00000=
0000 +0100
+++ wireless-testing/net/mac80211/mlme.c 2009-02-09 22:42:05.000000000 =
+0100
@@ -778,9 +778,6 @@ static void ieee80211_set_associated(str
bss_info_changed |=3D BSS_CHANGED_ASSOC;
ifsta->flags |=3D IEEE80211_STA_ASSOCIATED;
=20
- if (sdata->vif.type !=3D NL80211_IFTYPE_STATION)
- return;
-
bss =3D ieee80211_rx_bss_get(local, ifsta->bssid,
conf->channel->center_freq,
ifsta->ssid, ifsta->ssid_len);
@@ -1139,6 +1136,30 @@ static void ieee80211_auth_challenge(str
elems.challenge_len + 2, 1);
}
=20
+static void ieee80211_rx_mgmt_auth_ibss(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 (len < 24 + 6)
+ return;
+
+ auth_alg =3D le16_to_cpu(mgmt->u.auth.auth_alg);
+ auth_transaction =3D le16_to_cpu(mgmt->u.auth.auth_transaction);
+ status_code =3D le16_to_cpu(mgmt->u.auth.status_code);
+
+ /*
+ * IEEE 802.11 standard does not require authentication in IBSS
+ * networks and most implementations do not seem to use it.
+ * However, try to reply to authentication attempts if someone
+ * has actually implemented this.
+ */
+ if (auth_alg =3D=3D WLAN_AUTH_OPEN && auth_transaction =3D=3D 1)
+ 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,
@@ -1146,38 +1167,22 @@ static void ieee80211_rx_mgmt_auth(struc
{
u16 auth_alg, auth_transaction, status_code;
=20
- if (ifsta->state !=3D IEEE80211_STA_MLME_AUTHENTICATE &&
- sdata->vif.type !=3D NL80211_IFTYPE_ADHOC)
+ if (ifsta->state !=3D IEEE80211_STA_MLME_AUTHENTICATE)
return;
=20
if (len < 24 + 6)
return;
=20
- if (sdata->vif.type !=3D NL80211_IFTYPE_ADHOC &&
- memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) !=3D 0)
+ if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) !=3D 0)
return;
=20
- if (sdata->vif.type !=3D NL80211_IFTYPE_ADHOC &&
- memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) !=3D 0)
+ if (memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) !=3D 0)
return;
=20
auth_alg =3D le16_to_cpu(mgmt->u.auth.auth_alg);
auth_transaction =3D le16_to_cpu(mgmt->u.auth.auth_transaction);
status_code =3D le16_to_cpu(mgmt->u.auth.status_code);
=20
- if (sdata->vif.type =3D=3D NL80211_IFTYPE_ADHOC) {
- /*
- * IEEE 802.11 standard does not require authentication in IBSS
- * networks and most implementations do not seem to use it.
- * However, try to reply to authentication attempts if someone
- * has actually implemented this.
- */
- if (auth_alg !=3D WLAN_AUTH_OPEN || auth_transaction !=3D 1)
- return;
- ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0);
- return;
- }
-
if (auth_alg !=3D ifsta->auth_alg ||
auth_transaction !=3D ifsta->auth_transaction)
return;
@@ -1732,74 +1737,81 @@ static void ieee80211_rx_bss_info(struct
/* was just updated in ieee80211_bss_info_update */
beacon_timestamp =3D bss->cbss.tsf;
=20
- /*
- * In STA mode, the remaining parameters should not be overridden
- * by beacons because they're not necessarily accurate there.
- */
- if (sdata->vif.type !=3D NL80211_IFTYPE_ADHOC &&
- bss->last_probe_resp && beacon) {
- ieee80211_rx_bss_put(local, bss);
- return;
- }
+ if (sdata->vif.type !=3D NL80211_IFTYPE_ADHOC)
+ goto put_bss;
=20
/* check if we need to merge IBSS */
- if (sdata->vif.type =3D=3D NL80211_IFTYPE_ADHOC && beacon &&
- (!(sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)) &&
- bss->cbss.capability & WLAN_CAPABILITY_IBSS &&
- bss->cbss.channel =3D=3D local->oper_channel &&
- elems->ssid_len =3D=3D sdata->u.sta.ssid_len &&
+
+ /* merge only on beacons (???) */
+ if (!beacon)
+ goto put_bss;
+
+ /* 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 SSID */
+ if (elems->ssid_len !=3D sdata->u.sta.ssid_len ||
memcmp(elems->ssid, sdata->u.sta.ssid,
- sdata->u.sta.ssid_len) =3D=3D 0) {
- if (rx_status->flag & RX_FLAG_TSFT) {
- /* in order 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=C3=A2=C2=80=C2=99=
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
- * (=3D24 bytes * 8 usecs/byte) than the beacon timestamp.
- */
- int rate;
- if (rx_status->flag & RX_FLAG_HT) {
- rate =3D 65; /* TODO: HT rates */
- } else {
- rate =3D local->hw.wiphy->bands[band]->
- bitrates[rx_status->rate_idx].bitrate;
- }
- rx_timestamp =3D rx_status->mactime + (24 * 8 * 10 / rate);
- } else if (local && local->ops && local->ops->get_tsf)
- /* second best option: get current TSF */
- rx_timestamp =3D local->ops->get_tsf(local_to_hw(local));
+ sdata->u.sta.ssid_len))
+ goto put_bss;
+
+ if (rx_status->flag & RX_FLAG_TSFT) {
+ /*
+ * 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.
+ *
+ * E.g. at 1 MBit that means mactime is 192 usec earlier
+ * (=3D24 bytes * 8 usecs/byte) than the beacon timestamp.
+ */
+ int rate;
+
+ if (rx_status->flag & RX_FLAG_HT)
+ rate =3D 65; /* TODO: HT rates */
else
- /* can't merge without knowing the TSF */
- rx_timestamp =3D -1LLU;
+ rate =3D local->hw.wiphy->bands[band]->
+ bitrates[rx_status->rate_idx].bitrate;
+
+ rx_timestamp =3D rx_status->mactime + (24 * 8 * 10 / rate);
+ } else if (local && local->ops && local->ops->get_tsf)
+ /* second best option: get current TSF */
+ rx_timestamp =3D local->ops->get_tsf(local_to_hw(local));
+ else
+ /* can't merge without knowing the TSF */
+ rx_timestamp =3D -1LLU;
+
#ifdef CONFIG_MAC80211_IBSS_DEBUG
- printk(KERN_DEBUG "RX beacon SA=3D%pM BSSID=3D"
- "%pM TSF=3D0x%llx BCN=3D0x%llx diff=3D%lld @%lu\n",
- mgmt->sa, mgmt->bssid,
- (unsigned long long)rx_timestamp,
- (unsigned long long)beacon_timestamp,
- (unsigned long long)(rx_timestamp - beacon_timestamp),
- jiffies);
-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
- if (beacon_timestamp > rx_timestamp) {
+ printk(KERN_DEBUG "RX beacon SA=3D%pM BSSID=3D"
+ "%pM TSF=3D0x%llx BCN=3D0x%llx diff=3D%lld @%lu\n",
+ mgmt->sa, mgmt->bssid,
+ (unsigned long long)rx_timestamp,
+ (unsigned long long)beacon_timestamp,
+ (unsigned long long)(rx_timestamp - beacon_timestamp),
+ jiffies);
+#endif
+
+ if (beacon_timestamp > rx_timestamp) {
#ifdef CONFIG_MAC80211_IBSS_DEBUG
- printk(KERN_DEBUG "%s: beacon TSF higher than "
- "local TSF - IBSS merge with BSSID %pM\n",
- sdata->dev->name, mgmt->bssid);
+ printk(KERN_DEBUG "%s: beacon TSF higher than "
+ "local TSF - IBSS merge with BSSID %pM\n",
+ sdata->dev->name, mgmt->bssid);
#endif
- ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss);
- ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
- }
+ ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss);
+ ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
}
=20
+ put_bss:
ieee80211_rx_bss_put(local, bss);
}
=20
@@ -1948,8 +1960,7 @@ static void ieee80211_rx_mgmt_probe_req(
struct ieee80211_mgmt *resp;
u8 *pos, *end;
=20
- if (sdata->vif.type !=3D NL80211_IFTYPE_ADHOC ||
- ifsta->state !=3D IEEE80211_STA_MLME_IBSS_JOINED ||
+ if (ifsta->state !=3D IEEE80211_STA_MLME_IBSS_JOINED ||
len < 24 + 2 || !ifsta->probe_resp)
return;
=20
@@ -2053,31 +2064,54 @@ static void ieee80211_sta_rx_queued_mgmt
mgmt =3D (struct ieee80211_mgmt *) skb->data;
fc =3D le16_to_cpu(mgmt->frame_control);
=20
- switch (fc & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_PROBE_REQ:
- ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len);
- break;
- 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;
- case IEEE80211_STYPE_AUTH:
- ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len);
- break;
- case IEEE80211_STYPE_ASSOC_RESP:
- ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0);
- break;
- case IEEE80211_STYPE_REASSOC_RESP:
- ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1);
- break;
- case IEEE80211_STYPE_DEAUTH:
- ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len);
- break;
- case IEEE80211_STYPE_DISASSOC:
- ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len);
- break;
+ if (sdata->vif.type =3D=3D NL80211_IFTYPE_ADHOC) {
+ switch (fc & IEEE80211_FCTL_STYPE) {
+ case IEEE80211_STYPE_PROBE_REQ:
+ ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt,
+ skb->len);
+ break;
+ 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;
+ 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;
+ case IEEE80211_STYPE_AUTH:
+ ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len);
+ break;
+ case IEEE80211_STYPE_ASSOC_RESP:
+ ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt,
+ skb->len, 0);
+ break;
+ case IEEE80211_STYPE_REASSOC_RESP:
+ ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt,
+ skb->len, 1);
+ break;
+ case IEEE80211_STYPE_DEAUTH:
+ ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len);
+ break;
+ case IEEE80211_STYPE_DISASSOC:
+ ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt,
+ skb->len);
+ break;
+ }
}
=20
kfree_skb(skb);


2009-02-09 22:32:09

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] mac80211: split managed/ibss code a little more

On Mon, 2009-02-09 at 23:29 +0100, Alina Friedrichsen wrote:
> Hello Johannes!
>
> > 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,
>
> This is a huge change. Hopefully it doesn't break anything.

Hopefully; but it shouldn't. There was one strange thing with the
channel that I removed, we'll have to take a look at that maybe.

> Applying this patch fails for me. Can you please send me your mlme.c?

You need to apply the previous patch ("mac80211: fix IBSS auth") first.

johannes


Attachments:
signature.asc (836.00 B)
This is a digitally signed message part

2009-02-09 22:29:17

by Alina Friedrichsen

[permalink] [raw]
Subject: Re: [PATCH] mac80211: split managed/ibss code a little more

Hello Johannes!

> 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,=20

This is a huge change. Hopefully it doesn't break anything.

Applying this patch fails for me. Can you please send me your mlme.c?

Regards
Alina

--=20
Jetzt 1 Monat kostenlos! GMX FreeDSL - Telefonanschluss + DSL=20
f=FCr nur 17,95 Euro/mtl.!* http://dsl.gmx.de/?ac=3DOM.AD.PD003K11308T4=
569a