/* * Handle a station joining an RSN network. */ void ieee80211_node_join_rsn(struct ieee80211com *ic, struct ieee80211_node *ni) { DPRINTF(("station %s associated using proto %d akm 0x%x " "cipher 0x%x groupcipher 0x%x\n", ether_sprintf(ni->ni_macaddr), ni->ni_rsnprotos, ni->ni_rsnakms, ni->ni_rsnciphers, ni->ni_rsngroupcipher)); ni->ni_rsn_state = RSNA_AUTHENTICATION; ic->ic_rsnsta++; ni->ni_key_count = 0; ni->ni_port_valid = 0; ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT; ni->ni_replaycnt = -1; /* XXX */ ni->ni_rsn_retries = 0; ni->ni_rsncipher = ni->ni_rsnciphers; ni->ni_rsn_state = RSNA_AUTHENTICATION_2; /* generate a new authenticator nonce (ANonce) */ arc4random_buf(ni->ni_nonce, EAPOL_KEY_NONCE_LEN); if (!ieee80211_is_8021x_akm(ni->ni_rsnakms)) { memcpy(ni->ni_pmk, ic->ic_psk, IEEE80211_PMK_LEN); ni->ni_flags |= IEEE80211_NODE_PMK; (void)ieee80211_send_4way_msg1(ic, ni); } else if (ni->ni_flags & IEEE80211_NODE_PMK) { /* skip 802.1X auth if a cached PMK was found */ (void)ieee80211_send_4way_msg1(ic, ni); } else { /* no cached PMK found, needs full 802.1X auth */ ieee80211_needs_auth(ic, ni); } }
/* * Handle EAPOL-Key timeouts (no answer from supplicant). */ void ieee80211_eapol_timeout(void *arg) { struct ieee80211_node *ni = arg; struct ieee80211com *ic = ni->ni_ic; int s; DPRINTF(("no answer from station %s in state %d\n", ether_sprintf(ni->ni_macaddr), ni->ni_rsn_state)); s = splnet(); switch (ni->ni_rsn_state) { case RSNA_PTKSTART: case RSNA_PTKCALCNEGOTIATING: (void)ieee80211_send_4way_msg1(ic, ni); break; case RSNA_PTKINITNEGOTIATING: (void)ieee80211_send_4way_msg3(ic, ni); break; } switch (ni->ni_rsn_gstate) { case RSNA_REKEYNEGOTIATING: (void)ieee80211_send_group_msg1(ic, ni); break; } splx(s); }