static void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, int ver, const u8 *dest, u16 proto, u8 *msg, size_t msg_len, u8 *key_mic) { #if 0 if (os_memcmp(dest, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 && os_memcmp(sm->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) { /* * Association event was not yet received; try to fetch * BSSID from the driver. */ if (wpa_sm_get_bssid(sm, sm->bssid) < 0) { lwip_log("WPA: Failed to read BSSID for EAPOL-Key destination address\n"); } else { dest = sm->bssid; lwip_log("WPA: Use BSSID (" MACSTR ") as the destination for EAPOL-Key\n", MAC2STR(dest)); } } #endif //generate MIC. if (key_mic) { wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic); } wpa_ether_send(dest, proto, msg, msg_len); os_free(msg); }
/** * 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 (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; }
static int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto, const u8 *buf, size_t len) { return wpa_ether_send(wpa_s, dest, proto, buf, len); }
/** * 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; }