mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-04 06:54:27 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			243 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
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_newstate(struct ieee80211vap
 | 
						|
 				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,
 | 
						|
@@ -1358,12 +1358,14 @@ __ieee80211_newstate(struct ieee80211vap
 | 
						|
 				break;
 | 
						|
 			}
 | 
						|
 			goto reset;
 | 
						|
+		case IEEE80211_S_AUTH:
 | 
						|
 		case IEEE80211_S_ASSOC:
 | 
						|
 			switch (vap->iv_opmode) {
 | 
						|
 			case IEEE80211_M_STA:
 | 
						|
 				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 @@ __ieee80211_newstate(struct ieee80211vap
 | 
						|
 		case IEEE80211_S_SCAN:
 | 
						|
 			ieee80211_cancel_scan(vap);
 | 
						|
 			goto reset;
 | 
						|
-		case IEEE80211_S_AUTH:
 | 
						|
 		reset:
 | 
						|
 			ieee80211_reset_bss(vap);
 | 
						|
 			break;
 | 
						|
@@ -1429,10 +1430,12 @@ __ieee80211_newstate(struct ieee80211vap
 | 
						|
 					IEEE80211_SCAN_FOREVER,
 | 
						|
 					vap->iv_des_nssid, vap->iv_des_ssid,
 | 
						|
 					NULL);
 | 
						|
+			else
 | 
						|
+				ieee80211_node_leave(vap->iv_bss);
 | 
						|
 			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,
 | 
						|
@@ -1511,7 +1514,7 @@ __ieee80211_newstate(struct ieee80211vap
 | 
						|
 				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 ?
 | 
						|
@@ -1779,6 +1782,7 @@ ieee80211_newstate(struct ieee80211vap *
 | 
						|
 			  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 @@ ieee80211_vlan_vdetach(struct ieee80211v
 | 
						|
 }
 | 
						|
 
 | 
						|
 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 @@ ieee80211_notify_node_leave(struct ieee8
 | 
						|
 	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 @@ ieee80211_node_leave(struct ieee80211_no
 | 
						|
 		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 @@ ieee80211_node_leave(struct ieee80211_no
 | 
						|
 	 * (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
 | 
						|
@@ -2141,7 +2141,7 @@ ieee80211_send_mgmt(struct ieee80211_nod
 | 
						|
 
 | 
						|
 	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 @@ ieee80211_ioctl_siwap(struct net_device 
 | 
						|
 			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 @@ void ieee80211_vlan_vdetach(struct ieee8
 | 
						|
 #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;
 |