/** * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator * @ctx: Pointer to wpa_supplicant data (wpa_s) * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*) * @buf: EAPOL payload (after IEEE 802.1X header) * @len: EAPOL payload length * Returns: >=0 on success, <0 on failure * * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame * to the current Authenticator. */ static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, size_t len) { struct wpa_supplicant *wpa_s = ctx; u8 *msg, *dst, bssid[ETH_ALEN]; size_t msglen; int res; /* TODO: could add l2_packet_sendmsg that allows fragments to avoid * extra copy here */ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { /* Current SSID is not using IEEE 802.1X/EAP, so drop possible * EAPOL frames (mainly, EAPOL-Start) from EAPOL state * machines. */ wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X " "mode (type=%d len=%lu)", type, (unsigned long) len); return -1; } /*ALPS01472624: can't re-connect to CMCC-AUTO AP(ruijie) of MTK tower*/ #if 0 if (pmksa_cache_get_current(wpa_s->wpa) && type == IEEE802_1X_TYPE_EAPOL_START) { /* Trying to use PMKSA caching - do not send EAPOL-Start frames * since they will trigger full EAPOL authentication. */ wpa_printf(MSG_DEBUG, "RSN: PMKSA caching - do not send " "EAPOL-Start"); return -1; } #endif if (is_zero_ether_addr(wpa_s->bssid)) { wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an " "EAPOL frame"); if (wpa_drv_get_bssid(wpa_s, bssid) == 0 && !is_zero_ether_addr(bssid)) { dst = bssid; wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR " from the driver as the EAPOL destination", MAC2STR(dst)); } else { dst = wpa_s->last_eapol_src; wpa_printf(MSG_DEBUG, "Using the source address of the" " last received EAPOL frame " MACSTR " as " "the EAPOL destination", MAC2STR(dst)); } } else { /* BSSID was already set (from (Re)Assoc event, so use it as * the EAPOL destination. */ dst = wpa_s->bssid; } msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL); if (msg == NULL) return -1; wpa_printf(MSG_DEBUG, "TX EAPOL: dst=" MACSTR, MAC2STR(dst)); wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen); res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen); os_free(msg); return res; }
/** * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator * @ctx: Pointer to wpa_supplicant data (wpa_s) * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*) * @buf: EAPOL payload (after IEEE 802.1X header) * @len: EAPOL payload length * Returns: >=0 on success, <0 on failure * * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame * to the current Authenticator. */ static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, size_t len) { struct wpa_supplicant *wpa_s = ctx; u8 *msg, *dst, bssid[ETH_ALEN]; size_t msglen; int res; /* TODO: could add l2_packet_sendmsg that allows fragments to avoid * extra copy here */ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { /* Current SSID is not using IEEE 802.1X/EAP, so drop possible * EAPOL frames (mainly, EAPOL-Start) from EAPOL state * machines. */ wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X " "mode (type=%d len=%lu)", type, (unsigned long) len); return -1; } if (pmksa_cache_get_current(wpa_s->wpa) && type == IEEE802_1X_TYPE_EAPOL_START) { /* * We were trying to use PMKSA caching and sending EAPOL-Start * would abort that and trigger full EAPOL authentication. * However, we've already waited for the AP/Authenticator to * start 4-way handshake or EAP authentication, and apparently * it has not done so since the startWhen timer has reached zero * to get the state machine sending EAPOL-Start. This is not * really supposed to happen, but an interoperability issue with * a deployed AP has been identified where the connection fails * due to that AP failing to operate correctly if PMKID is * included in the Association Request frame. To work around * this, assume PMKSA caching failed and try to initiate full * EAP authentication. */ if (!wpa_s->current_ssid || wpa_s->current_ssid->eap_workaround) { wpa_printf(MSG_DEBUG, "RSN: Timeout on waiting for the AP to initiate 4-way handshake for PMKSA caching or EAP authentication - try to force it to start EAP authentication"); } else { wpa_printf(MSG_DEBUG, "RSN: PMKSA caching - do not send EAPOL-Start"); return -1; } } if (is_zero_ether_addr(wpa_s->bssid)) { wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an " "EAPOL frame"); if (wpa_drv_get_bssid(wpa_s, bssid) == 0 && !is_zero_ether_addr(bssid)) { dst = bssid; wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR " from the driver as the EAPOL destination", MAC2STR(dst)); } else { dst = wpa_s->last_eapol_src; wpa_printf(MSG_DEBUG, "Using the source address of the" " last received EAPOL frame " MACSTR " as " "the EAPOL destination", MAC2STR(dst)); } } else { /* BSSID was already set (from (Re)Assoc event, so use it as * the EAPOL destination. */ dst = wpa_s->bssid; } msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL); if (msg == NULL) return -1; wpa_printf(MSG_DEBUG, "TX EAPOL: dst=" MACSTR, MAC2STR(dst)); wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen); res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen); os_free(msg); return res; }