On Wed, Aug 28, 2019 at 05:07:34PM +0200, Stefan Sperling wrote:
> On Wed, Aug 28, 2019 at 04:52:10PM +0200, Stefan Sperling wrote:
> > On Wed, Aug 28, 2019 at 04:18:41PM +0200, Stefan Sperling wrote:
> > > Updated diff below.
> >
> > And this is another update which changes display of failure codes
> > from "!(foo.bar)" to "!foo,!bar", as suggested off-list by Theo.
> >
> > This should make the output easier to parse.
>
> Now with less new lines added by making printb_status() more flexible.
Another (hopefully final) update:
Theo suggested putting ! directly into the bitstring macro which keeps
things simpler for ifconfig.
Also, a background scan implies that we are already associated. While we are
associated, we only care about failures for APs belonging to the network
we are associated to, so don't update failure flags for unrelated APs when
processing the result of a background scan.
And clear old failure flags once we have recomputed failures based on
latest scan results.
diff refs/heads/master refs/heads/assocfail
blob - 543e09f0d6e6b4e75456a21d4218468729b61a5e
blob + 42ad3819f5688690ebee46d01274f54907066e67
--- sbin/ifconfig/ifconfig.c
+++ sbin/ifconfig/ifconfig.c
@@ -2348,10 +2348,25 @@ print_cipherset(u_int32_t cipherset)
}
void
+print_assoc_failures(uint32_t assoc_fail)
+{
+ /* Filter out the most obvious failure cases. */
+ assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_ESSID;
+ if (assoc_fail & IEEE80211_NODEREQ_ASSOCFAIL_PRIVACY)
+ assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_WPA_PROTO;
+ assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_PRIVACY;
+
+ if (assoc_fail == 0)
+ return;
+
+ printb_status(assoc_fail, IEEE80211_NODEREQ_ASSOCFAIL_BITS);
+}
+
+void
ieee80211_status(void)
{
int len, inwid, ijoin, inwkey, ipsk, ichan, ipwr;
- int ibssid, iwpa;
+ int ibssid, iwpa, assocfail = 0;
struct ieee80211_nwid nwid;
struct ieee80211_join join;
struct ieee80211_nwkey nwkey;
@@ -2431,11 +2446,15 @@ ieee80211_status(void)
bzero(&nr, sizeof(nr));
bcopy(bssid.i_bssid, &nr.nr_macaddr, sizeof(nr.nr_macaddr));
strlcpy(nr.nr_ifname, name, sizeof(nr.nr_ifname));
- if (ioctl(s, SIOCG80211NODE, &nr) == 0 && nr.nr_rssi) {
- if (nr.nr_max_rssi)
- printf(" %u%%", IEEE80211_NODEREQ_RSSI(&nr));
- else
- printf(" %ddBm", nr.nr_rssi);
+ if (ioctl(s, SIOCG80211NODE, &nr) == 0) {
+ if (nr.nr_rssi) {
+ if (nr.nr_max_rssi)
+ printf(" %u%%",
+ IEEE80211_NODEREQ_RSSI(&nr));
+ else
+ printf(" %ddBm", nr.nr_rssi);
+ }
+ assocfail = nr.nr_assoc_fail;
}
}
@@ -2478,6 +2497,11 @@ ieee80211_status(void)
putchar(' ');
printb_status(ifr.ifr_flags, IEEE80211_F_USERBITS);
}
+
+ if (assocfail) {
+ putchar(' ');
+ print_assoc_failures(assocfail);
+ }
putchar('\n');
if (show_join)
join_status();
@@ -2751,6 +2775,8 @@ ieee80211_printnode(struct ieee80211_nodereq *nr)
if ((nr->nr_flags & IEEE80211_NODEREQ_AP) == 0)
printb_status(IEEE80211_NODEREQ_STATE(nr->nr_state),
IEEE80211_NODEREQ_STATE_BITS);
+ else if (nr->nr_assoc_fail)
+ print_assoc_failures(nr->nr_assoc_fail);
}
void
blob - 425ee5f5a726e3fe0445c82debb0469d4878407f
blob + 6b3b8a5834db39d5b2f2dc7693f42d0b5adbcfbb
--- sys/net80211/ieee80211_ioctl.c
+++ sys/net80211/ieee80211_ioctl.c
@@ -104,6 +104,7 @@ ieee80211_node2req(struct ieee80211com *ic, const stru
nr->nr_txseq = ni->ni_txseq;
nr->nr_rxseq = ni->ni_rxseq;
nr->nr_fails = ni->ni_fails;
+ nr->nr_assoc_fail = ni->ni_assoc_fail; /* flag values are the same */
nr->nr_inact = ni->ni_inact;
nr->nr_txrate = ni->ni_txrate;
nr->nr_state = ni->ni_state;
@@ -821,7 +822,11 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t
break;
case SIOCG80211NODE:
nr = (struct ieee80211_nodereq *)data;
- ni = ieee80211_find_node(ic, nr->nr_macaddr);
+ if (ic->ic_bss &&
+ IEEE80211_ADDR_EQ(nr->nr_macaddr, ic->ic_bss->ni_macaddr))
+ ni = ic->ic_bss;
+ else
+ ni = ieee80211_find_node(ic, nr->nr_macaddr);
if (ni == NULL) {
error = ENOENT;
break;
blob - 575a573d2e21e9863bdab5276471f32fd189cc57
blob + 6a53566afc4594afeecf9834055f31af3d021b9f
--- sys/net80211/ieee80211_ioctl.h
+++ sys/net80211/ieee80211_ioctl.h
@@ -359,6 +359,8 @@ struct ieee80211_nodereq {
/* VHT */
uint8_t nr_vht_ss;
+
+ u_int32_t nr_assoc_fail; /* association failure reasons */
};
#define IEEE80211_NODEREQ_STATE(_s) (1 << _s)
@@ -378,6 +380,18 @@ struct ieee80211_nodereq {
#define SIOCG80211NODE _IOWR('i', 211, struct ieee80211_nodereq)
#define SIOCS80211NODE _IOW('i', 212, struct ieee80211_nodereq)
#define SIOCS80211DELNODE _IOW('i', 213, struct ieee80211_nodereq)
+
+#define IEEE80211_NODEREQ_ASSOCFAIL_CHAN 0x01
+#define IEEE80211_NODEREQ_ASSOCFAIL_IBSS 0x02
+#define IEEE80211_NODEREQ_ASSOCFAIL_PRIVACY 0x04
+#define IEEE80211_NODEREQ_ASSOCFAIL_BASIC_RATE 0x08
+#define IEEE80211_NODEREQ_ASSOCFAIL_ESSID 0x10
+#define IEEE80211_NODEREQ_ASSOCFAIL_BSSID 0x20
+#define IEEE80211_NODEREQ_ASSOCFAIL_WPA_PROTO 0x40
+#define IEEE80211_NODEREQ_ASSOCFAIL_WPA_KEY 0x80
+#define IEEE80211_NODEREQ_ASSOCFAIL_BITS \
+ "\20\1!CHAN\2!IBSS\3!PRIVACY\4!BASICRATE\5!ESSID\6!BSSID\7!WPAPROTO" \
+ "\10!WPAKEY"
/* get the entire node cache */
struct ieee80211_nodereq_all {
blob - 99b17a709fec1326d108be8e39ae8596f5b7f0f6
blob + 93238443fea9ca5f17d7f739617b295da5d1d3f7
--- sys/net80211/ieee80211_node.c
+++ sys/net80211/ieee80211_node.c
@@ -523,28 +523,40 @@ ieee80211_match_ess(struct ieee80211_ess *ess, struct
{
if (ess->esslen != 0 &&
(ess->esslen != ni->ni_esslen ||
- memcmp(ess->essid, ni->ni_essid, ess->esslen) != 0))
+ memcmp(ess->essid, ni->ni_essid, ess->esslen) != 0)) {
+ ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_ESSID;
return 0;
+ }
if (ess->flags & (IEEE80211_F_PSK | IEEE80211_F_RSNON)) {
/* Ensure same WPA version. */
if ((ni->ni_rsnprotos & IEEE80211_PROTO_RSN) &&
- (ess->rsnprotos & IEEE80211_PROTO_RSN) == 0)
+ (ess->rsnprotos & IEEE80211_PROTO_RSN) == 0) {
+ ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;
return 0;
+ }
if ((ni->ni_rsnprotos & IEEE80211_PROTO_WPA) &&
- (ess->rsnprotos & IEEE80211_PROTO_WPA) == 0)
+ (ess->rsnprotos & IEEE80211_PROTO_WPA) == 0) {
+ ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;
return 0;
+ }
} else if (ess->flags & IEEE80211_F_WEPON) {
- if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
+ if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0) {
+ ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_PRIVACY;
return 0;
+ }
} else {
- if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) != 0)
+ if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) != 0) {
+ ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_PRIVACY;
return 0;
+ }
}
if (ess->esslen == 0 &&
- (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) != 0)
+ (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) != 0) {
+ ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_PRIVACY;
return 0;
+ }
return 1;
}
@@ -780,7 +792,7 @@ ieee80211_reset_scan(struct ifnet *ifp)
}
/*
- * Increase a node's inactitivy counter.
+ * Increase a node's inactivity counter.
* This counter get reset to zero if a frame is received.
* This function is intended for station mode only.
* See ieee80211_node_cache_timeout() for hostap mode.
@@ -993,48 +1005,49 @@ ieee80211_create_ibss(struct ieee80211com* ic, struct
#endif /* IEEE80211_STA_ONLY */
int
-ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
+ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni,
+ int bgscan)
{
u_int8_t rate;
int fail;
fail = 0;
if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
- fail |= 0x01;
+ fail |= IEEE80211_NODE_ASSOCFAIL_CHAN;
if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
ni->ni_chan != ic->ic_des_chan)
- fail |= 0x01;
+ fail |= IEEE80211_NODE_ASSOCFAIL_CHAN;
#ifndef IEEE80211_STA_ONLY
if (ic->ic_opmode == IEEE80211_M_IBSS) {
if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
- fail |= 0x02;
+ fail |= IEEE80211_NODE_ASSOCFAIL_IBSS;
} else
#endif
{
if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
- fail |= 0x02;
+ fail |= IEEE80211_NODE_ASSOCFAIL_IBSS;
}
if (ic->ic_flags & (IEEE80211_F_WEPON | IEEE80211_F_RSNON)) {
if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
- fail |= 0x04;
+ fail |= IEEE80211_NODE_ASSOCFAIL_PRIVACY;
} else {
if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
- fail |= 0x04;
+ fail |= IEEE80211_NODE_ASSOCFAIL_PRIVACY;
}
rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO);
if (rate & IEEE80211_RATE_BASIC)
- fail |= 0x08;
+ fail |= IEEE80211_NODE_ASSOCFAIL_BASIC_RATE;
if (ISSET(ic->ic_flags, IEEE80211_F_AUTO_JOIN) &&
ic->ic_des_esslen == 0)
- fail |= 0x10;
+ fail |= IEEE80211_NODE_ASSOCFAIL_ESSID;
if (ic->ic_des_esslen != 0 &&
(ni->ni_esslen != ic->ic_des_esslen ||
memcmp(ni->ni_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0))
- fail |= 0x10;
+ fail |= IEEE80211_NODE_ASSOCFAIL_ESSID;
if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
!IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
- fail |= 0x20;
+ fail |= IEEE80211_NODE_ASSOCFAIL_BSSID;
if (ic->ic_flags & IEEE80211_F_RSNON) {
/*
@@ -1043,66 +1056,76 @@ ieee80211_match_bss(struct ieee80211com *ic, struct ie
* decline to associate with that AP.
*/
if ((ni->ni_rsnprotos & ic->ic_rsnprotos) == 0)
- fail |= 0x40;
+ fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;
if ((ni->ni_rsnakms & ic->ic_rsnakms) == 0)
- fail |= 0x40;
+ fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;
if ((ni->ni_rsnakms & ic->ic_rsnakms &
~(IEEE80211_AKM_PSK | IEEE80211_AKM_SHA256_PSK)) == 0) {
/* AP only supports PSK AKMPs */
if (!(ic->ic_flags & IEEE80211_F_PSK))
- fail |= 0x40;
+ fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;
}
if (ni->ni_rsngroupcipher != IEEE80211_CIPHER_WEP40 &&
ni->ni_rsngroupcipher != IEEE80211_CIPHER_TKIP &&
ni->ni_rsngroupcipher != IEEE80211_CIPHER_CCMP &&
ni->ni_rsngroupcipher != IEEE80211_CIPHER_WEP104)
- fail |= 0x40;
+ fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;
if ((ni->ni_rsnciphers & ic->ic_rsnciphers) == 0)
- fail |= 0x40;
+ fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;
/* we only support BIP as the IGTK cipher */
if ((ni->ni_rsncaps & IEEE80211_RSNCAP_MFPC) &&
ni->ni_rsngroupmgmtcipher != IEEE80211_CIPHER_BIP)
- fail |= 0x40;
+ fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;
/* we do not support MFP but AP requires it */
if (!(ic->ic_caps & IEEE80211_C_MFP) &&
(ni->ni_rsncaps & IEEE80211_RSNCAP_MFPR))
- fail |= 0x40;
+ fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;
/* we require MFP but AP does not support it */
if ((ic->ic_caps & IEEE80211_C_MFP) &&
(ic->ic_flags & IEEE80211_F_MFPR) &&
!(ni->ni_rsncaps & IEEE80211_RSNCAP_MFPC))
- fail |= 0x40;
+ fail |= IEEE80211_NODE_ASSOCFAIL_WPA_PROTO;
}
if (ic->ic_if.if_flags & IFF_DEBUG) {
printf("%s: %c %s%c", ic->ic_if.if_xname, fail ? '-' : '+',
ether_sprintf(ni->ni_bssid),
- fail & 0x20 ? '!' : ' ');
+ fail & IEEE80211_NODE_ASSOCFAIL_BSSID ? '!' : ' ');
printf(" %3d%c", ieee80211_chan2ieee(ic, ni->ni_chan),
- fail & 0x01 ? '!' : ' ');
+ fail & IEEE80211_NODE_ASSOCFAIL_CHAN ? '!' : ' ');
printf(" %+4d", ni->ni_rssi);
printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
- fail & 0x08 ? '!' : ' ');
+ fail & IEEE80211_NODE_ASSOCFAIL_BASIC_RATE ? '!' : ' ');
printf(" %4s%c",
(ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
(ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
"????",
- fail & 0x02 ? '!' : ' ');
+ fail & IEEE80211_NODE_ASSOCFAIL_IBSS ? '!' : ' ');
printf(" %7s%c ",
(ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
"privacy" : "no",
- fail & 0x04 ? '!' : ' ');
+ fail & IEEE80211_NODE_ASSOCFAIL_PRIVACY ? '!' : ' ');
printf(" %3s%c ",
(ic->ic_flags & IEEE80211_F_RSNON) ?
"rsn" : "no",
- fail & 0x40 ? '!' : ' ');
+ fail & IEEE80211_NODE_ASSOCFAIL_WPA_PROTO ? '!' : ' ');
ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
- printf("%s\n", fail & 0x10 ? "!" : "");
+ printf("%s\n",
+ fail & IEEE80211_NODE_ASSOCFAIL_ESSID ? "!" : "");
}
+ /* We don't care about unrelated networks during background scans. */
+ if (bgscan) {
+ if ((fail & IEEE80211_NODE_ASSOCFAIL_ESSID) == 0)
+ ni->ni_assoc_fail = fail;
+ } else
+ ni->ni_assoc_fail = fail;
+ if ((fail & IEEE80211_NODE_ASSOCFAIL_ESSID) == 0)
+ ic->ic_bss->ni_assoc_fail = ni->ni_assoc_fail;
+
return fail;
}
@@ -1160,15 +1183,25 @@ ieee80211_node_join_bss(struct ieee80211com *ic, struc
{
enum ieee80211_phymode mode;
struct ieee80211_node *ni;
+ uint32_t assoc_fail = 0;
/* Reinitialize media mode and channels if needed. */
mode = ieee80211_chan2mode(ic, selbs->ni_chan);
if (mode != ic->ic_curmode)
ieee80211_setmode(ic, mode);
+ /* Keep recorded association failures for this BSS/ESS intact. */
+ if (IEEE80211_ADDR_EQ(ic->ic_bss->ni_macaddr, selbs->ni_macaddr) ||
+ (ic->ic_des_esslen > 0 && ic->ic_des_esslen == selbs->ni_esslen &&
+ memcmp(ic->ic_des_essid, selbs->ni_essid, selbs->ni_esslen) == 0))
+ assoc_fail = ic->ic_bss->ni_assoc_fail;
+
(*ic->ic_node_copy)(ic, ic->ic_bss, selbs);
ni = ic->ic_bss;
+ ni->ni_assoc_fail |= assoc_fail;
+ ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan);
+
/* Make sure we send valid rates in an association request. */
if (ic->ic_opmode == IEEE80211_M_STA)
ieee80211_fix_rate(ic, ni,
@@ -1249,7 +1282,7 @@ ieee80211_node_choose_bss(struct ieee80211com *ic, int
if (curbs && ieee80211_node_cmp(ic->ic_bss, ni) == 0)
*curbs = ni;
- if (ieee80211_match_bss(ic, ni) != 0)
+ if (ieee80211_match_bss(ic, ni, bgscan) != 0)
continue;
if (ic->ic_caps & IEEE80211_C_SCANALLBAND) {
@@ -2822,7 +2855,7 @@ ieee80211_ibss_merge(struct ieee80211com *ic, struct i
if (sign < 0)
return 0;
- if (ieee80211_match_bss(ic, ni) != 0)
+ if (ieee80211_match_bss(ic, ni, 0) != 0)
return 0;
if (ieee80211_do_slow_print(ic, &did_print)) {
blob - b2b80656a4b4aa907b4d729ecaecb81827739c52
blob + 081e0eee78221d039ff3a9811598333b3a83deff
--- sys/net80211/ieee80211_node.h
+++ sys/net80211/ieee80211_node.h
@@ -353,6 +353,16 @@ struct ieee80211_node {
u_int16_t ni_qos_txseqs[IEEE80211_NUM_TID];
u_int16_t ni_qos_rxseqs[IEEE80211_NUM_TID];
int ni_fails; /* failure count to associate */
+ uint32_t ni_assoc_fail; /* assoc failure reasons */
+#define IEEE80211_NODE_ASSOCFAIL_CHAN 0x01
+#define IEEE80211_NODE_ASSOCFAIL_IBSS 0x02
+#define IEEE80211_NODE_ASSOCFAIL_PRIVACY 0x04
+#define IEEE80211_NODE_ASSOCFAIL_BASIC_RATE 0x08
+#define IEEE80211_NODE_ASSOCFAIL_ESSID 0x10
+#define IEEE80211_NODE_ASSOCFAIL_BSSID 0x20
+#define IEEE80211_NODE_ASSOCFAIL_WPA_PROTO 0x40
+#define IEEE80211_NODE_ASSOCFAIL_WPA_KEY 0x80
+
int ni_inact; /* inactivity mark count */
int ni_txrate; /* index to ni_rates[] */
int ni_state;
@@ -515,8 +525,7 @@ void ieee80211_node_join(struct ieee80211com *,
struct ieee80211_node *, int);
void ieee80211_node_leave(struct ieee80211com *,
struct ieee80211_node *);
-int ieee80211_match_bss(struct ieee80211com *,
- struct ieee80211_node *);
+int ieee80211_match_bss(struct ieee80211com *, struct ieee80211_node *, int);
struct ieee80211_node *ieee80211_node_choose_bss(struct ieee80211com *, int,
struct ieee80211_node **);
void ieee80211_node_join_bss(struct ieee80211com *, struct ieee80211_node *);
blob - ba8c1872a2df596a0667ecb7c306f7e7f9dd0ffc
blob + 3ab5bacb42d9990898dd11db2e74a29ad3330b53
--- sys/net80211/ieee80211_pae_input.c
+++ sys/net80211/ieee80211_pae_input.c
@@ -650,6 +650,7 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
ether_sprintf(ni->ni_macaddr)));
ni->ni_port_valid = 1;
ieee80211_set_link_state(ic, LINK_STATE_UP);
+ ni->ni_assoc_fail = 0;
}
}
deauth:
@@ -915,6 +916,7 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
ether_sprintf(ni->ni_macaddr)));
ni->ni_port_valid = 1;
ieee80211_set_link_state(ic, LINK_STATE_UP);
+ ni->ni_assoc_fail = 0;
}
}
/* update the last seen value of the key replay counter field */
@@ -1019,6 +1021,7 @@ ieee80211_recv_wpa_group_msg1(struct ieee80211com *ic,
ether_sprintf(ni->ni_macaddr)));
ni->ni_port_valid = 1;
ieee80211_set_link_state(ic, LINK_STATE_UP);
+ ni->ni_assoc_fail = 0;
}
}
/* update the last seen value of the key replay counter field */
blob - 30c784c7b2f404dcdb35d37a8b1b29928f628184
blob + 5ab07bfe2215a99449a86e073bc474ed238ae6b3
--- sys/net80211/ieee80211_proto.c
+++ sys/net80211/ieee80211_proto.c
@@ -939,6 +939,30 @@ ieee80211_stop_ampdu_tx(struct ieee80211com *ic, struc
}
}
+void
+ieee80211_check_wpa_supplicant_failure(struct ieee80211com *ic,
+ struct ieee80211_node *ni)
+{
+ struct ieee80211_node *ni2;
+
+ if (ic->ic_opmode != IEEE80211_M_STA &&
+ ic->ic_opmode != IEEE80211_M_IBSS)
+ return;
+
+ if (ni->ni_rsn_supp_state != RSNA_SUPP_PTKNEGOTIATING)
+ return;
+
+ ni->ni_assoc_fail |= IEEE80211_NODE_ASSOCFAIL_WPA_KEY;
+
+ if (ni != ic->ic_bss)
+ return;
+
+ /* Also update the copy of our AP's node in the node cache. */
+ ni2 = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr);
+ if (ni2)
+ ni2->ni_assoc_fail |= ic->ic_bss->ni_assoc_fail;
+}
+
int
ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,
int mgt)
@@ -1037,6 +1061,7 @@ justcleanup:
break;
}
ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
+ ni->ni_assoc_fail = 0;
if (ic->ic_flags & IEEE80211_F_RSNON)
ieee80211_crypto_clear_groupkeys(ic);
break;
@@ -1097,6 +1122,8 @@ justcleanup:
}
break;
case IEEE80211_S_AUTH:
+ if (ostate == IEEE80211_S_RUN)
+ ieee80211_check_wpa_supplicant_failure(ic, ni);
ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
if (ic->ic_flags & IEEE80211_F_RSNON)
ieee80211_crypto_clear_groupkeys(ic);
@@ -1218,6 +1245,7 @@ justcleanup:
* the link up until the port is valid.
*/
ieee80211_set_link_state(ic, LINK_STATE_UP);
+ ni->ni_assoc_fail = 0;
}
ic->ic_mgt_timer = 0;
ieee80211_set_beacon_miss_threshold(ic);