| 1 | Drop stale AP nodes from the client list when disconnecting. |
| 2 | Fixes some reassoc issues. |
| 3 | |
| 4 | Signed-off-by: Felix Fietkau <nbd@openwrt.org> |
| 5 | |
| 6 | --- a/net80211/ieee80211_proto.c |
| 7 | +++ b/net80211/ieee80211_proto.c |
| 8 | @@ -1348,7 +1348,7 @@ __ieee80211_newstate(struct ieee80211vap |
| 9 | IEEE80211_SEND_MGMT(ni, |
| 10 | IEEE80211_FC0_SUBTYPE_DISASSOC, |
| 11 | IEEE80211_REASON_ASSOC_LEAVE); |
| 12 | - ieee80211_sta_leave(ni); |
| 13 | + ieee80211_node_leave(ni); |
| 14 | break; |
| 15 | case IEEE80211_M_HOSTAP: |
| 16 | ieee80211_iterate_nodes(&ic->ic_sta, |
| 17 | @@ -1358,12 +1358,14 @@ __ieee80211_newstate(struct ieee80211vap |
| 18 | break; |
| 19 | } |
| 20 | goto reset; |
| 21 | + case IEEE80211_S_AUTH: |
| 22 | case IEEE80211_S_ASSOC: |
| 23 | switch (vap->iv_opmode) { |
| 24 | case IEEE80211_M_STA: |
| 25 | IEEE80211_SEND_MGMT(ni, |
| 26 | IEEE80211_FC0_SUBTYPE_DEAUTH, |
| 27 | IEEE80211_REASON_AUTH_LEAVE); |
| 28 | + ieee80211_node_leave(ni); |
| 29 | break; |
| 30 | case IEEE80211_M_HOSTAP: |
| 31 | ieee80211_iterate_nodes(&ic->ic_sta, |
| 32 | @@ -1376,7 +1378,6 @@ __ieee80211_newstate(struct ieee80211vap |
| 33 | case IEEE80211_S_SCAN: |
| 34 | ieee80211_cancel_scan(vap); |
| 35 | goto reset; |
| 36 | - case IEEE80211_S_AUTH: |
| 37 | reset: |
| 38 | ieee80211_reset_bss(vap); |
| 39 | break; |
| 40 | @@ -1429,10 +1430,12 @@ __ieee80211_newstate(struct ieee80211vap |
| 41 | IEEE80211_SCAN_FOREVER, |
| 42 | vap->iv_des_nssid, vap->iv_des_ssid, |
| 43 | NULL); |
| 44 | + else |
| 45 | + ieee80211_node_leave(vap->iv_bss); |
| 46 | break; |
| 47 | case IEEE80211_S_RUN: /* beacon miss */ |
| 48 | if (vap->iv_opmode == IEEE80211_M_STA) { |
| 49 | - ieee80211_sta_leave(ni); |
| 50 | + ieee80211_node_leave(ni); |
| 51 | vap->iv_flags &= ~IEEE80211_F_SIBSS; /* XXX */ |
| 52 | if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) |
| 53 | ieee80211_check_scan(vap, |
| 54 | @@ -1511,7 +1514,7 @@ __ieee80211_newstate(struct ieee80211vap |
| 55 | IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); |
| 56 | break; |
| 57 | case IEEE80211_S_RUN: |
| 58 | - ieee80211_sta_leave(ni); |
| 59 | + ieee80211_node_leave(ni); |
| 60 | if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) { |
| 61 | /* NB: caller specifies ASSOC/REASSOC by arg */ |
| 62 | IEEE80211_SEND_MGMT(ni, arg ? |
| 63 | @@ -1779,6 +1782,7 @@ ieee80211_newstate(struct ieee80211vap * |
| 64 | ieee80211_state_name[nstate], |
| 65 | ieee80211_state_name[dstate]); |
| 66 | |
| 67 | + ieee80211_update_link_status(vap, nstate, ostate); |
| 68 | switch (nstate) { |
| 69 | case IEEE80211_S_AUTH: |
| 70 | case IEEE80211_S_ASSOC: |
| 71 | --- a/net80211/ieee80211_linux.c |
| 72 | +++ b/net80211/ieee80211_linux.c |
| 73 | @@ -233,33 +233,59 @@ ieee80211_vlan_vdetach(struct ieee80211v |
| 74 | } |
| 75 | |
| 76 | void |
| 77 | -ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc) |
| 78 | +ieee80211_update_link_status(struct ieee80211vap *vap, int nstate, int ostate) |
| 79 | { |
| 80 | - struct ieee80211vap *vap = ni->ni_vap; |
| 81 | struct net_device *dev = vap->iv_dev; |
| 82 | union iwreq_data wreq; |
| 83 | + int active; |
| 84 | + |
| 85 | + if (vap->iv_opmode != IEEE80211_M_STA) |
| 86 | + return; |
| 87 | + |
| 88 | + if (ostate == nstate) |
| 89 | + return; |
| 90 | + |
| 91 | + if (nstate == IEEE80211_S_RUN) |
| 92 | + active = 1; |
| 93 | + else if ((ostate >= IEEE80211_S_AUTH) && (nstate < ostate)) |
| 94 | + active = 0; |
| 95 | + else |
| 96 | + return; |
| 97 | + |
| 98 | + if (active && !vap->iv_bss) |
| 99 | + return; |
| 100 | + |
| 101 | + memset(&wreq, 0, sizeof(wreq)); |
| 102 | + wreq.ap_addr.sa_family = ARPHRD_ETHER; |
| 103 | |
| 104 | - if (ni == vap->iv_bss) { |
| 105 | - if (newassoc) |
| 106 | - netif_carrier_on(dev); |
| 107 | - memset(&wreq, 0, sizeof(wreq)); |
| 108 | + if (active) { |
| 109 | + //netif_carrier_on(vap->iv_dev); |
| 110 | IEEE80211_ADDR_COPY(wreq.addr.sa_data, vap->iv_bssid); |
| 111 | - wreq.addr.sa_family = ARPHRD_ETHER; |
| 112 | -#ifdef ATH_SUPERG_XR |
| 113 | - if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR) |
| 114 | - dev = vap->iv_xrvap->iv_dev; |
| 115 | -#endif |
| 116 | - wireless_send_event(dev, SIOCGIWAP, &wreq, NULL); |
| 117 | } else { |
| 118 | - memset(&wreq, 0, sizeof(wreq)); |
| 119 | - IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr); |
| 120 | - wreq.addr.sa_family = ARPHRD_ETHER; |
| 121 | + //netif_carrier_off(vap->iv_dev); |
| 122 | + memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN); |
| 123 | + } |
| 124 | + wireless_send_event(dev, SIOCGIWAP, &wreq, NULL); |
| 125 | +} |
| 126 | + |
| 127 | +void |
| 128 | +ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc) |
| 129 | +{ |
| 130 | + struct ieee80211vap *vap = ni->ni_vap; |
| 131 | + struct net_device *dev = vap->iv_dev; |
| 132 | + union iwreq_data wreq; |
| 133 | + |
| 134 | + if (ni == vap->iv_bss) |
| 135 | + return; |
| 136 | + |
| 137 | + memset(&wreq, 0, sizeof(wreq)); |
| 138 | + IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr); |
| 139 | + wreq.addr.sa_family = ARPHRD_ETHER; |
| 140 | #ifdef ATH_SUPERG_XR |
| 141 | - if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR) |
| 142 | - dev = vap->iv_xrvap->iv_dev; |
| 143 | + if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR) |
| 144 | + dev = vap->iv_xrvap->iv_dev; |
| 145 | #endif |
| 146 | - wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL); |
| 147 | - } |
| 148 | + wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL); |
| 149 | } |
| 150 | |
| 151 | void |
| 152 | @@ -269,18 +295,14 @@ ieee80211_notify_node_leave(struct ieee8 |
| 153 | struct net_device *dev = vap->iv_dev; |
| 154 | union iwreq_data wreq; |
| 155 | |
| 156 | - if (ni == vap->iv_bss) { |
| 157 | - netif_carrier_off(dev); |
| 158 | - memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN); |
| 159 | - wreq.ap_addr.sa_family = ARPHRD_ETHER; |
| 160 | - wireless_send_event(dev, SIOCGIWAP, &wreq, NULL); |
| 161 | - } else { |
| 162 | - /* fire off wireless event station leaving */ |
| 163 | - memset(&wreq, 0, sizeof(wreq)); |
| 164 | - IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr); |
| 165 | - wreq.addr.sa_family = ARPHRD_ETHER; |
| 166 | - wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL); |
| 167 | - } |
| 168 | + if (ni == vap->iv_bss) |
| 169 | + return; |
| 170 | + |
| 171 | + /* fire off wireless event station leaving */ |
| 172 | + memset(&wreq, 0, sizeof(wreq)); |
| 173 | + IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr); |
| 174 | + wreq.addr.sa_family = ARPHRD_ETHER; |
| 175 | + wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL); |
| 176 | } |
| 177 | |
| 178 | void |
| 179 | --- a/net80211/ieee80211_node.c |
| 180 | +++ b/net80211/ieee80211_node.c |
| 181 | @@ -2332,6 +2332,7 @@ ieee80211_node_leave(struct ieee80211_no |
| 182 | count_suppchans(ic, ni, -1); |
| 183 | IEEE80211_UNLOCK_IRQ(ic); |
| 184 | |
| 185 | +done: |
| 186 | /* |
| 187 | * Cleanup station state. In particular clear various |
| 188 | * state that might otherwise be reused if the node |
| 189 | @@ -2339,7 +2340,7 @@ ieee80211_node_leave(struct ieee80211_no |
| 190 | * (and memory is reclaimed). |
| 191 | */ |
| 192 | ieee80211_sta_leave(ni); |
| 193 | -done: |
| 194 | + |
| 195 | /* Run a cleanup */ |
| 196 | #ifdef IEEE80211_DEBUG_REFCNT |
| 197 | ic->ic_node_cleanup_debug(ni, __func__, __LINE__); |
| 198 | --- a/net80211/ieee80211_node.h |
| 199 | +++ b/net80211/ieee80211_node.h |
| 200 | @@ -60,7 +60,7 @@ |
| 201 | #define IEEE80211_INACT_PROBE (30/IEEE80211_INACT_WAIT) /* probe */ |
| 202 | #define IEEE80211_INACT_SCAN (300/IEEE80211_INACT_WAIT) /* scanned */ |
| 203 | |
| 204 | -#define IEEE80211_TRANS_WAIT 5 /* mgt frame tx timer (secs) */ |
| 205 | +#define IEEE80211_TRANS_WAIT 300 /* mgt frame tx timer (msecs) */ |
| 206 | |
| 207 | #define IEEE80211_NODE_HASHSIZE 32 |
| 208 | /* simple hash is enough for variation of macaddr */ |
| 209 | --- a/net80211/ieee80211_output.c |
| 210 | +++ b/net80211/ieee80211_output.c |
| 211 | @@ -2141,7 +2141,7 @@ ieee80211_send_mgmt(struct ieee80211_nod |
| 212 | |
| 213 | ieee80211_mgmt_output(ieee80211_ref_node(ni), skb, type); |
| 214 | if (timer) |
| 215 | - mod_timer(&vap->iv_mgtsend, jiffies + timer * HZ); |
| 216 | + mod_timer(&vap->iv_mgtsend, jiffies + msecs_to_jiffies(timer)); |
| 217 | return 0; |
| 218 | bad: |
| 219 | return ret; |
| 220 | --- a/net80211/ieee80211_wireless.c |
| 221 | +++ b/net80211/ieee80211_wireless.c |
| 222 | @@ -514,8 +514,9 @@ ieee80211_ioctl_siwap(struct net_device |
| 223 | vap->iv_flags |= IEEE80211_F_DESBSSID; |
| 224 | |
| 225 | IEEE80211_ADDR_COPY(vap->iv_des_bssid, &ap_addr->sa_data); |
| 226 | - if (IS_UP_AUTO(vap)) |
| 227 | + if (IS_UP(vap->iv_dev)) { |
| 228 | ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); |
| 229 | + } |
| 230 | } |
| 231 | return 0; |
| 232 | } |
| 233 | --- a/net80211/ieee80211_linux.h |
| 234 | +++ b/net80211/ieee80211_linux.h |
| 235 | @@ -643,6 +643,7 @@ void ieee80211_vlan_vdetach(struct ieee8 |
| 236 | #define free_netdev(dev) kfree(dev) |
| 237 | #endif |
| 238 | |
| 239 | +void ieee80211_update_link_status(struct ieee80211vap *vap, int nstate, int ostate); |
| 240 | void ieee80211_ioctl_vattach(struct ieee80211vap *); |
| 241 | void ieee80211_ioctl_vdetach(struct ieee80211vap *); |
| 242 | struct ifreq; |
| 243 | |