2008-07-12 22:24:26 +00:00
|
|
|
Drop stale AP nodes from the client list when disconnecting.
|
|
|
|
Fixes some reassoc issues.
|
|
|
|
|
|
|
|
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
|
|
|
|
|
|
|
--- a/net80211/ieee80211_proto.c
|
|
|
|
+++ b/net80211/ieee80211_proto.c
|
|
|
|
@@ -1348,7 +1348,7 @@
|
|
|
|
IEEE80211_SEND_MGMT(ni,
|
|
|
|
IEEE80211_FC0_SUBTYPE_DISASSOC,
|
|
|
|
IEEE80211_REASON_ASSOC_LEAVE);
|
|
|
|
- ieee80211_sta_leave(ni);
|
|
|
|
+ ieee80211_node_leave(ni);
|
|
|
|
break;
|
|
|
|
case IEEE80211_M_HOSTAP:
|
|
|
|
ieee80211_iterate_nodes(&ic->ic_sta,
|
2008-07-25 22:36:33 +00:00
|
|
|
@@ -1358,12 +1358,14 @@
|
2008-07-12 22:24:26 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
goto reset;
|
|
|
|
+ case IEEE80211_S_AUTH:
|
|
|
|
case IEEE80211_S_ASSOC:
|
|
|
|
switch (vap->iv_opmode) {
|
|
|
|
case IEEE80211_M_STA:
|
2008-07-25 22:36:33 +00:00
|
|
|
IEEE80211_SEND_MGMT(ni,
|
|
|
|
IEEE80211_FC0_SUBTYPE_DEAUTH,
|
|
|
|
IEEE80211_REASON_AUTH_LEAVE);
|
|
|
|
+ ieee80211_node_leave(ni);
|
|
|
|
break;
|
|
|
|
case IEEE80211_M_HOSTAP:
|
|
|
|
ieee80211_iterate_nodes(&ic->ic_sta,
|
|
|
|
@@ -1376,7 +1378,6 @@
|
2008-07-12 22:24:26 +00:00
|
|
|
case IEEE80211_S_SCAN:
|
|
|
|
ieee80211_cancel_scan(vap);
|
|
|
|
goto reset;
|
|
|
|
- case IEEE80211_S_AUTH:
|
|
|
|
reset:
|
|
|
|
ieee80211_reset_bss(vap);
|
|
|
|
break;
|
2008-07-25 22:36:33 +00:00
|
|
|
@@ -1429,10 +1430,12 @@
|
|
|
|
IEEE80211_SCAN_FOREVER,
|
|
|
|
vap->iv_des_nssid, vap->iv_des_ssid,
|
|
|
|
NULL);
|
|
|
|
+ else
|
|
|
|
+ ieee80211_node_leave(vap->iv_bss);
|
2008-07-12 22:24:26 +00:00
|
|
|
break;
|
|
|
|
case IEEE80211_S_RUN: /* beacon miss */
|
|
|
|
if (vap->iv_opmode == IEEE80211_M_STA) {
|
|
|
|
- ieee80211_sta_leave(ni);
|
|
|
|
+ ieee80211_node_leave(ni);
|
|
|
|
vap->iv_flags &= ~IEEE80211_F_SIBSS; /* XXX */
|
|
|
|
if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
|
|
|
|
ieee80211_check_scan(vap,
|
2008-07-25 22:36:33 +00:00
|
|
|
@@ -1511,7 +1514,7 @@
|
2008-07-12 22:24:26 +00:00
|
|
|
IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
|
|
|
|
break;
|
|
|
|
case IEEE80211_S_RUN:
|
|
|
|
- ieee80211_sta_leave(ni);
|
|
|
|
+ ieee80211_node_leave(ni);
|
|
|
|
if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
|
|
|
|
/* NB: caller specifies ASSOC/REASSOC by arg */
|
|
|
|
IEEE80211_SEND_MGMT(ni, arg ?
|
2008-07-25 22:36:33 +00:00
|
|
|
@@ -1779,6 +1782,7 @@
|
|
|
|
ieee80211_state_name[nstate],
|
|
|
|
ieee80211_state_name[dstate]);
|
|
|
|
|
|
|
|
+ ieee80211_update_link_status(vap, nstate, ostate);
|
|
|
|
switch (nstate) {
|
|
|
|
case IEEE80211_S_AUTH:
|
|
|
|
case IEEE80211_S_ASSOC:
|
|
|
|
--- a/net80211/ieee80211_linux.c
|
|
|
|
+++ b/net80211/ieee80211_linux.c
|
|
|
|
@@ -233,33 +233,59 @@
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
-ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc)
|
|
|
|
+ieee80211_update_link_status(struct ieee80211vap *vap, int nstate, int ostate)
|
|
|
|
{
|
|
|
|
- struct ieee80211vap *vap = ni->ni_vap;
|
|
|
|
struct net_device *dev = vap->iv_dev;
|
|
|
|
union iwreq_data wreq;
|
|
|
|
+ int active;
|
|
|
|
+
|
|
|
|
+ if (vap->iv_opmode != IEEE80211_M_STA)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (ostate == nstate)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (nstate == IEEE80211_S_RUN)
|
|
|
|
+ active = 1;
|
|
|
|
+ else if ((ostate >= IEEE80211_S_AUTH) && (nstate < ostate))
|
|
|
|
+ active = 0;
|
|
|
|
+ else
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (active && !vap->iv_bss)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ memset(&wreq, 0, sizeof(wreq));
|
|
|
|
+ wreq.ap_addr.sa_family = ARPHRD_ETHER;
|
|
|
|
|
|
|
|
- if (ni == vap->iv_bss) {
|
|
|
|
- if (newassoc)
|
|
|
|
- netif_carrier_on(dev);
|
|
|
|
- memset(&wreq, 0, sizeof(wreq));
|
|
|
|
+ if (active) {
|
|
|
|
+ //netif_carrier_on(vap->iv_dev);
|
|
|
|
IEEE80211_ADDR_COPY(wreq.addr.sa_data, vap->iv_bssid);
|
|
|
|
- wreq.addr.sa_family = ARPHRD_ETHER;
|
|
|
|
-#ifdef ATH_SUPERG_XR
|
|
|
|
- if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
|
|
|
|
- dev = vap->iv_xrvap->iv_dev;
|
|
|
|
-#endif
|
|
|
|
- wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
|
|
|
|
} else {
|
|
|
|
- memset(&wreq, 0, sizeof(wreq));
|
|
|
|
- IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
|
|
|
|
- wreq.addr.sa_family = ARPHRD_ETHER;
|
|
|
|
+ //netif_carrier_off(vap->iv_dev);
|
|
|
|
+ memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN);
|
|
|
|
+ }
|
|
|
|
+ wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc)
|
|
|
|
+{
|
|
|
|
+ struct ieee80211vap *vap = ni->ni_vap;
|
|
|
|
+ struct net_device *dev = vap->iv_dev;
|
|
|
|
+ union iwreq_data wreq;
|
|
|
|
+
|
|
|
|
+ if (ni == vap->iv_bss)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ memset(&wreq, 0, sizeof(wreq));
|
|
|
|
+ IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
|
|
|
|
+ wreq.addr.sa_family = ARPHRD_ETHER;
|
|
|
|
#ifdef ATH_SUPERG_XR
|
|
|
|
- if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
|
|
|
|
- dev = vap->iv_xrvap->iv_dev;
|
|
|
|
+ if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
|
|
|
|
+ dev = vap->iv_xrvap->iv_dev;
|
|
|
|
#endif
|
|
|
|
- wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);
|
|
|
|
- }
|
|
|
|
+ wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
@@ -269,18 +295,14 @@
|
|
|
|
struct net_device *dev = vap->iv_dev;
|
|
|
|
union iwreq_data wreq;
|
|
|
|
|
|
|
|
- if (ni == vap->iv_bss) {
|
|
|
|
- netif_carrier_off(dev);
|
|
|
|
- memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN);
|
|
|
|
- wreq.ap_addr.sa_family = ARPHRD_ETHER;
|
|
|
|
- wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
|
|
|
|
- } else {
|
|
|
|
- /* fire off wireless event station leaving */
|
|
|
|
- memset(&wreq, 0, sizeof(wreq));
|
|
|
|
- IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
|
|
|
|
- wreq.addr.sa_family = ARPHRD_ETHER;
|
|
|
|
- wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL);
|
|
|
|
- }
|
|
|
|
+ if (ni == vap->iv_bss)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ /* fire off wireless event station leaving */
|
|
|
|
+ memset(&wreq, 0, sizeof(wreq));
|
|
|
|
+ IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
|
|
|
|
+ wreq.addr.sa_family = ARPHRD_ETHER;
|
|
|
|
+ wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
--- a/net80211/ieee80211_node.c
|
|
|
|
+++ b/net80211/ieee80211_node.c
|
|
|
|
@@ -2332,6 +2332,7 @@
|
|
|
|
count_suppchans(ic, ni, -1);
|
|
|
|
IEEE80211_UNLOCK_IRQ(ic);
|
|
|
|
|
|
|
|
+done:
|
|
|
|
/*
|
|
|
|
* Cleanup station state. In particular clear various
|
|
|
|
* state that might otherwise be reused if the node
|
|
|
|
@@ -2339,7 +2340,7 @@
|
|
|
|
* (and memory is reclaimed).
|
|
|
|
*/
|
|
|
|
ieee80211_sta_leave(ni);
|
|
|
|
-done:
|
|
|
|
+
|
|
|
|
/* Run a cleanup */
|
|
|
|
#ifdef IEEE80211_DEBUG_REFCNT
|
|
|
|
ic->ic_node_cleanup_debug(ni, __func__, __LINE__);
|
|
|
|
--- a/net80211/ieee80211_node.h
|
|
|
|
+++ b/net80211/ieee80211_node.h
|
|
|
|
@@ -60,7 +60,7 @@
|
|
|
|
#define IEEE80211_INACT_PROBE (30/IEEE80211_INACT_WAIT) /* probe */
|
|
|
|
#define IEEE80211_INACT_SCAN (300/IEEE80211_INACT_WAIT) /* scanned */
|
|
|
|
|
|
|
|
-#define IEEE80211_TRANS_WAIT 5 /* mgt frame tx timer (secs) */
|
|
|
|
+#define IEEE80211_TRANS_WAIT 300 /* mgt frame tx timer (msecs) */
|
|
|
|
|
|
|
|
#define IEEE80211_NODE_HASHSIZE 32
|
|
|
|
/* simple hash is enough for variation of macaddr */
|
|
|
|
--- a/net80211/ieee80211_output.c
|
|
|
|
+++ b/net80211/ieee80211_output.c
|
2008-07-25 22:41:13 +00:00
|
|
|
@@ -2141,7 +2141,7 @@
|
2008-07-25 22:36:33 +00:00
|
|
|
|
|
|
|
ieee80211_mgmt_output(ieee80211_ref_node(ni), skb, type);
|
|
|
|
if (timer)
|
|
|
|
- mod_timer(&vap->iv_mgtsend, jiffies + timer * HZ);
|
|
|
|
+ mod_timer(&vap->iv_mgtsend, jiffies + msecs_to_jiffies(timer));
|
|
|
|
return 0;
|
|
|
|
bad:
|
|
|
|
return ret;
|
|
|
|
--- a/net80211/ieee80211_wireless.c
|
|
|
|
+++ b/net80211/ieee80211_wireless.c
|
|
|
|
@@ -514,8 +514,9 @@
|
|
|
|
vap->iv_flags |= IEEE80211_F_DESBSSID;
|
|
|
|
|
|
|
|
IEEE80211_ADDR_COPY(vap->iv_des_bssid, &ap_addr->sa_data);
|
|
|
|
- if (IS_UP_AUTO(vap))
|
|
|
|
+ if (IS_UP(vap->iv_dev)) {
|
|
|
|
ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
|
|
|
|
+ }
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
--- a/net80211/ieee80211_linux.h
|
|
|
|
+++ b/net80211/ieee80211_linux.h
|
|
|
|
@@ -643,6 +643,7 @@
|
|
|
|
#define free_netdev(dev) kfree(dev)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
+void ieee80211_update_link_status(struct ieee80211vap *vap, int nstate, int ostate);
|
|
|
|
void ieee80211_ioctl_vattach(struct ieee80211vap *);
|
|
|
|
void ieee80211_ioctl_vdetach(struct ieee80211vap *);
|
|
|
|
struct ifreq;
|