linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Userspace (wpa_supplicant) not notified on interface down with 2.6.29/wireless-testing
@ 2009-03-09 21:50 Herton Ronaldo Krzesinski
  2009-03-10  7:13 ` Johannes Berg
  0 siblings, 1 reply; 3+ messages in thread
From: Herton Ronaldo Krzesinski @ 2009-03-09 21:50 UTC (permalink / raw)
  To: linux-wireless, Johannes Berg; +Cc: John W. Linville

I have the problem when using 2.6.29 and judging by the code the situation
stays the same with wireless-testing, even after the fix "mac80211: deauth when
interface is marked down" (the fix doesn't work with kernel 2.6.28 or later, as
I'll explain).

The problem is, with latest kernels wpa_supplicant isn't still notified when
interface goes down, even after commit "mac80211: deauth when interface is
marked down" (e327b847 on Linus tree). There isn't a problem with this commit,
but because of other code changes it doesn't work on latest kernels (but works
if I apply same/similar change on 2.6.27 for example).

The issue is as follows: after commit "mac80211: restructure disassoc/deauth
flows" in 2.6.28, the call to ieee80211_sta_deauthenticate added by commit
e327b847 will not work: because we do sta_info_flush(local, sdata); inside
ieee80211_stop (iface.c), all stations in interface are cleared, so when calling
 ieee80211_sta_deauthenticate->ieee80211_set_disassoc (mlme.c), inside
ieee80211_set_disassoc we have this in the beginning:

        sta = sta_info_get(local, ifsta->bssid);
        if (!sta) {

the !sta check triggers, so the function returns early and
ieee80211_sta_send_apinfo(sdata, ifsta); later isn't called, so wpa_supplicant
isn't notified with SIOCGIWAP

One possible fix is moving sta_info_flush, to avoid !sta, and seems good, like
the following:

diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 2acc416..0929581 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -370,25 +370,6 @@ static int ieee80211_stop(struct net_device *dev)
 	rcu_read_unlock();
 
 	/*
-	 * Remove all stations associated with this interface.
-	 *
-	 * This must be done before calling ops->remove_interface()
-	 * because otherwise we can later invoke ops->sta_notify()
-	 * whenever the STAs are removed, and that invalidates driver
-	 * assumptions about always getting a vif pointer that is valid
-	 * (because if we remove a STA after ops->remove_interface()
-	 * the driver will have removed the vif info already!)
-	 *
-	 * We could relax this and only unlink the stations from the
-	 * hash table and list but keep them on a per-sdata list that
-	 * will be inserted back again when the interface is brought
-	 * up again, but I don't currently see a use case for that,
-	 * except with WDS which gets a STA entry created when it is
-	 * brought up.
-	 */
-	sta_info_flush(local, sdata);
-
-	/*
 	 * Don't count this interface for promisc/allmulti while it
 	 * is down. dev_mc_unsync() will invoke set_multicast_list
 	 * on the master interface which will sync these down to the
@@ -539,6 +520,26 @@ static int ieee80211_stop(struct net_device *dev)
 		conf.mac_addr = dev->dev_addr;
 		/* disable all keys for as long as this netdev is down */
 		ieee80211_disable_keys(sdata);
+
+		/*
+		 * Remove all stations associated with this interface.
+		 *
+		 * This must be done before calling ops->remove_interface()
+		 * because otherwise we can later invoke ops->sta_notify()
+		 * whenever the STAs are removed, and that invalidates driver
+		 * assumptions about always getting a vif pointer that is valid
+		 * (because if we remove a STA after ops->remove_interface()
+		 * the driver will have removed the vif info already!)
+		 *
+		 * We could relax this and only unlink the stations from the
+		 * hash table and list but keep them on a per-sdata list that
+		 * will be inserted back again when the interface is brought
+		 * up again, but I don't currently see a use case for that,
+		 * except with WDS which gets a STA entry created when it is
+		 * brought up.
+		 */
+		sta_info_flush(local, sdata);
+
 		local->ops->remove_interface(local_to_hw(local), &conf);
 	}
 
My question is, is the patch above safe? that is, do we need to always
call sta_info_flush on interface down like currently, or just for the case we
call remove_interface, like the comment states? if the latter, patch above
is good, and solves the wpa_supplicant/userspace issue.

--
[]'s
Herton.

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: Userspace (wpa_supplicant) not notified on interface down with 2.6.29/wireless-testing
  2009-03-09 21:50 Userspace (wpa_supplicant) not notified on interface down with 2.6.29/wireless-testing Herton Ronaldo Krzesinski
@ 2009-03-10  7:13 ` Johannes Berg
  2009-03-10 13:11   ` Herton Ronaldo Krzesinski
  0 siblings, 1 reply; 3+ messages in thread
From: Johannes Berg @ 2009-03-10  7:13 UTC (permalink / raw)
  To: Herton Ronaldo Krzesinski; +Cc: linux-wireless, John W. Linville

[-- Attachment #1: Type: text/plain, Size: 4627 bytes --]

On Mon, 2009-03-09 at 18:50 -0300, Herton Ronaldo Krzesinski wrote:
> I have the problem when using 2.6.29 and judging by the code the situation
> stays the same with wireless-testing, even after the fix "mac80211: deauth when
> interface is marked down" (the fix doesn't work with kernel 2.6.28 or later, as
> I'll explain).
> 
> The problem is, with latest kernels wpa_supplicant isn't still notified when
> interface goes down, even after commit "mac80211: deauth when interface is
> marked down" (e327b847 on Linus tree). There isn't a problem with this commit,
> but because of other code changes it doesn't work on latest kernels (but works
> if I apply same/similar change on 2.6.27 for example).
> 
> The issue is as follows: after commit "mac80211: restructure disassoc/deauth
> flows" in 2.6.28, the call to ieee80211_sta_deauthenticate added by commit
> e327b847 will not work: because we do sta_info_flush(local, sdata); inside
> ieee80211_stop (iface.c), all stations in interface are cleared, so when calling
>  ieee80211_sta_deauthenticate->ieee80211_set_disassoc (mlme.c), inside
> ieee80211_set_disassoc we have this in the beginning:
> 
>         sta = sta_info_get(local, ifsta->bssid);
>         if (!sta) {
> 
> the !sta check triggers, so the function returns early and
> ieee80211_sta_send_apinfo(sdata, ifsta); later isn't called, so wpa_supplicant
> isn't notified with SIOCGIWAP

Interesting problem.

> One possible fix is moving sta_info_flush, to avoid !sta, and seems good, like
> the following:
> 
> diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
> index 2acc416..0929581 100644
> --- a/net/mac80211/iface.c
> +++ b/net/mac80211/iface.c
> @@ -370,25 +370,6 @@ static int ieee80211_stop(struct net_device *dev)
>  	rcu_read_unlock();
>  
>  	/*
> -	 * Remove all stations associated with this interface.
> -	 *
> -	 * This must be done before calling ops->remove_interface()
> -	 * because otherwise we can later invoke ops->sta_notify()
> -	 * whenever the STAs are removed, and that invalidates driver
> -	 * assumptions about always getting a vif pointer that is valid
> -	 * (because if we remove a STA after ops->remove_interface()
> -	 * the driver will have removed the vif info already!)
> -	 *
> -	 * We could relax this and only unlink the stations from the
> -	 * hash table and list but keep them on a per-sdata list that
> -	 * will be inserted back again when the interface is brought
> -	 * up again, but I don't currently see a use case for that,
> -	 * except with WDS which gets a STA entry created when it is
> -	 * brought up.
> -	 */
> -	sta_info_flush(local, sdata);
> -
> -	/*
>  	 * Don't count this interface for promisc/allmulti while it
>  	 * is down. dev_mc_unsync() will invoke set_multicast_list
>  	 * on the master interface which will sync these down to the
> @@ -539,6 +520,26 @@ static int ieee80211_stop(struct net_device *dev)
>  		conf.mac_addr = dev->dev_addr;
>  		/* disable all keys for as long as this netdev is down */
>  		ieee80211_disable_keys(sdata);
> +
> +		/*
> +		 * Remove all stations associated with this interface.
> +		 *
> +		 * This must be done before calling ops->remove_interface()
> +		 * because otherwise we can later invoke ops->sta_notify()
> +		 * whenever the STAs are removed, and that invalidates driver
> +		 * assumptions about always getting a vif pointer that is valid
> +		 * (because if we remove a STA after ops->remove_interface()
> +		 * the driver will have removed the vif info already!)
> +		 *
> +		 * We could relax this and only unlink the stations from the
> +		 * hash table and list but keep them on a per-sdata list that
> +		 * will be inserted back again when the interface is brought
> +		 * up again, but I don't currently see a use case for that,
> +		 * except with WDS which gets a STA entry created when it is
> +		 * brought up.
> +		 */
> +		sta_info_flush(local, sdata);
> +
>  		local->ops->remove_interface(local_to_hw(local), &conf);
>  	}
>  
> My question is, is the patch above safe? that is, do we need to always
> call sta_info_flush on interface down like currently, or just for the case we
> call remove_interface, like the comment states? if the latter, patch above
> is good, and solves the wpa_supplicant/userspace issue.

The comment states it must be before remove_interface, not that it
doesn't need to be called unless that is called, and this code moving is
incorrect for AP_VLAN devices.

You could move the disassoc part out of the switch to before this.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Userspace (wpa_supplicant) not notified on interface down with 2.6.29/wireless-testing
  2009-03-10  7:13 ` Johannes Berg
@ 2009-03-10 13:11   ` Herton Ronaldo Krzesinski
  0 siblings, 0 replies; 3+ messages in thread
From: Herton Ronaldo Krzesinski @ 2009-03-10 13:11 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, John W. Linville

Em Ter=E7a-feira 10 Mar=E7o 2009, =E0s 04:13:34, Johannes Berg escreveu=
:
> On Mon, 2009-03-09 at 18:50 -0300, Herton Ronaldo Krzesinski wrote:
> > I have the problem when using 2.6.29 and judging by the code the si=
tuation
> > stays the same with wireless-testing, even after the fix "mac80211:=
 deauth when
> > interface is marked down" (the fix doesn't work with kernel 2.6.28 =
or later, as
> > I'll explain).
> >=20
> > The problem is, with latest kernels wpa_supplicant isn't still noti=
fied when
> > interface goes down, even after commit "mac80211: deauth when inter=
face is
> > marked down" (e327b847 on Linus tree). There isn't a problem with t=
his commit,
> > but because of other code changes it doesn't work on latest kernels=
 (but works
> > if I apply same/similar change on 2.6.27 for example).
> >=20
> > The issue is as follows: after commit "mac80211: restructure disass=
oc/deauth
> > flows" in 2.6.28, the call to ieee80211_sta_deauthenticate added by=
 commit
> > e327b847 will not work: because we do sta_info_flush(local, sdata);=
 inside
> > ieee80211_stop (iface.c), all stations in interface are cleared, so=
 when calling
> >  ieee80211_sta_deauthenticate->ieee80211_set_disassoc (mlme.c), ins=
ide
> > ieee80211_set_disassoc we have this in the beginning:
> >=20
> >         sta =3D sta_info_get(local, ifsta->bssid);
> >         if (!sta) {
> >=20
> > the !sta check triggers, so the function returns early and
> > ieee80211_sta_send_apinfo(sdata, ifsta); later isn't called, so wpa=
_supplicant
> > isn't notified with SIOCGIWAP
>=20
> Interesting problem.
>=20
> > One possible fix is moving sta_info_flush, to avoid !sta, and seems=
 good, like
> > the following:
> >=20
> > diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
> > index 2acc416..0929581 100644
> > --- a/net/mac80211/iface.c
> > +++ b/net/mac80211/iface.c
> > @@ -370,25 +370,6 @@ static int ieee80211_stop(struct net_device *d=
ev)
> >  	rcu_read_unlock();
> > =20
> >  	/*
> > -	 * Remove all stations associated with this interface.
> > -	 *
> > -	 * This must be done before calling ops->remove_interface()
> > -	 * because otherwise we can later invoke ops->sta_notify()
> > -	 * whenever the STAs are removed, and that invalidates driver
> > -	 * assumptions about always getting a vif pointer that is valid
> > -	 * (because if we remove a STA after ops->remove_interface()
> > -	 * the driver will have removed the vif info already!)
> > -	 *
> > -	 * We could relax this and only unlink the stations from the
> > -	 * hash table and list but keep them on a per-sdata list that
> > -	 * will be inserted back again when the interface is brought
> > -	 * up again, but I don't currently see a use case for that,
> > -	 * except with WDS which gets a STA entry created when it is
> > -	 * brought up.
> > -	 */
> > -	sta_info_flush(local, sdata);
> > -
> > -	/*
> >  	 * Don't count this interface for promisc/allmulti while it
> >  	 * is down. dev_mc_unsync() will invoke set_multicast_list
> >  	 * on the master interface which will sync these down to the
> > @@ -539,6 +520,26 @@ static int ieee80211_stop(struct net_device *d=
ev)
> >  		conf.mac_addr =3D dev->dev_addr;
> >  		/* disable all keys for as long as this netdev is down */
> >  		ieee80211_disable_keys(sdata);
> > +
> > +		/*
> > +		 * Remove all stations associated with this interface.
> > +		 *
> > +		 * This must be done before calling ops->remove_interface()
> > +		 * because otherwise we can later invoke ops->sta_notify()
> > +		 * whenever the STAs are removed, and that invalidates driver
> > +		 * assumptions about always getting a vif pointer that is valid
> > +		 * (because if we remove a STA after ops->remove_interface()
> > +		 * the driver will have removed the vif info already!)
> > +		 *
> > +		 * We could relax this and only unlink the stations from the
> > +		 * hash table and list but keep them on a per-sdata list that
> > +		 * will be inserted back again when the interface is brought
> > +		 * up again, but I don't currently see a use case for that,
> > +		 * except with WDS which gets a STA entry created when it is
> > +		 * brought up.
> > +		 */
> > +		sta_info_flush(local, sdata);
> > +
> >  		local->ops->remove_interface(local_to_hw(local), &conf);
> >  	}
> > =20
> > My question is, is the patch above safe? that is, do we need to alw=
ays
> > call sta_info_flush on interface down like currently, or just for t=
he case we
> > call remove_interface, like the comment states? if the latter, patc=
h above
> > is good, and solves the wpa_supplicant/userspace issue.
>=20
> The comment states it must be before remove_interface, not that it
> doesn't need to be called unless that is called, and this code moving=
 is
> incorrect for AP_VLAN devices.
>=20
> You could move the disassoc part out of the switch to before this.

Ok, here is the new patch, if it's ok please apply (I can resubmit with=
 patch
in subject/standalone message if necessary):

=46rom eb6f79597b9e6af8a3618873a781fd6ebcbd50a0 Mon Sep 17 00:00:00 200=
1
=46rom: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
Date: Tue, 10 Mar 2009 09:44:17 -0300
Subject: [PATCH] mac80211: deauth before flushing STA information

Even after commit "mac80211: deauth when interface is marked down"
(e327b847 on Linus tree), userspace still isn't notified when interface
goes down. There isn't a problem with this commit, but because of other
code changes it doesn't work on kernels >=3D 2.6.28 (works if same/simi=
lar
change applied on 2.6.27 for example).

The issue is as follows: after commit "mac80211: restructure disassoc/d=
eauth
flows" in 2.6.28, the call to ieee80211_sta_deauthenticate added by
commit e327b847 will not work: because we do sta_info_flush(local, sdat=
a)
inside ieee80211_stop (iface.c), all stations in interface are cleared,=
 so
when calling ieee80211_sta_deauthenticate->ieee80211_set_disassoc (mlme=
=2Ec),
inside ieee80211_set_disassoc we have this in the beginning:

         sta =3D sta_info_get(local, ifsta->bssid);
         if (!sta) {

The !sta check triggers, thus the function returns early and
ieee80211_sta_send_apinfo(sdata, ifsta) later isn't called, so
wpa_supplicant/userspace isn't notified with SIOCGIWAP.

This commit moves deauthentication to before flushing STA info
(sta_info_flush), thus the above can't happen and userspace is really
notified when interface goes down.

Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
---
 net/mac80211/iface.c |   16 ++++++++++++----
 1 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 2acc416..f9f27b9 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -370,6 +370,18 @@ static int ieee80211_stop(struct net_device *dev)
 	rcu_read_unlock();
=20
 	/*
+	 * Announce that we are leaving the network, in case we are a
+	 * station interface type. This must be done before removing
+	 * all stations associated with sta_info_flush, otherwise STA
+	 * information will be gone and no announce being done.
+	 */
+	if (sdata->vif.type =3D=3D NL80211_IFTYPE_STATION) {
+		if (sdata->u.mgd.state !=3D IEEE80211_STA_MLME_DISABLED)
+			ieee80211_sta_deauthenticate(sdata,
+				WLAN_REASON_DEAUTH_LEAVING);
+	}
+
+	/*
 	 * Remove all stations associated with this interface.
 	 *
 	 * This must be done before calling ops->remove_interface()
@@ -454,10 +466,6 @@ static int ieee80211_stop(struct net_device *dev)
 		netif_addr_unlock_bh(local->mdev);
 		break;
 	case NL80211_IFTYPE_STATION:
-		/* Announce that we are leaving the network. */
-		if (sdata->u.mgd.state !=3D IEEE80211_STA_MLME_DISABLED)
-			ieee80211_sta_deauthenticate(sdata,
-						WLAN_REASON_DEAUTH_LEAVING);
 		memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
 		del_timer_sync(&sdata->u.mgd.chswitch_timer);
 		del_timer_sync(&sdata->u.mgd.timer);
--=20
1.6.2

>=20
> johannes
>=20

--
[]'s
Herton
--
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-03-10 13:11 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-09 21:50 Userspace (wpa_supplicant) not notified on interface down with 2.6.29/wireless-testing Herton Ronaldo Krzesinski
2009-03-10  7:13 ` Johannes Berg
2009-03-10 13:11   ` Herton Ronaldo Krzesinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).