wpa_supplicant AP: Add EAPOL frame TX and RX
This allows WPA-Personal 4-way handshake to be completed successfully.
This commit is contained in:
parent
07d9a55297
commit
db149ac949
5 changed files with 111 additions and 71 deletions
|
@ -2885,6 +2885,76 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
|
|||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
||||
|
||||
static int wpa_driver_nl80211_hapd_send_eapol(
|
||||
void *priv, const u8 *addr, const u8 *data,
|
||||
size_t data_len, int encrypt, const u8 *own_addr)
|
||||
{
|
||||
struct wpa_driver_nl80211_data *drv = priv;
|
||||
struct ieee80211_hdr *hdr;
|
||||
size_t len;
|
||||
u8 *pos;
|
||||
int res;
|
||||
#if 0 /* FIX */
|
||||
int qos = sta->flags & WLAN_STA_WME;
|
||||
#else
|
||||
int qos = 0;
|
||||
#endif
|
||||
|
||||
len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
|
||||
data_len;
|
||||
hdr = os_zalloc(len);
|
||||
if (hdr == NULL) {
|
||||
printf("malloc() failed for i802_send_data(len=%lu)\n",
|
||||
(unsigned long) len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdr->frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
|
||||
hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
|
||||
if (encrypt)
|
||||
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
|
||||
#if 0 /* To be enabled if qos determination is added above */
|
||||
if (qos) {
|
||||
hdr->frame_control |=
|
||||
host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
|
||||
memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
|
||||
memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
|
||||
pos = (u8 *) (hdr + 1);
|
||||
|
||||
#if 0 /* To be enabled if qos determination is added above */
|
||||
if (qos) {
|
||||
/* add an empty QoS header if needed */
|
||||
pos[0] = 0;
|
||||
pos[1] = 0;
|
||||
pos += 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
|
||||
pos += sizeof(rfc1042_header);
|
||||
WPA_PUT_BE16(pos, ETH_P_PAE);
|
||||
pos += 2;
|
||||
memcpy(pos, data, data_len);
|
||||
|
||||
res = wpa_driver_nl80211_send_frame(drv, (u8 *) hdr, len, encrypt);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
|
||||
"failed: %d (%s)",
|
||||
(unsigned long) len, errno, strerror(errno));
|
||||
}
|
||||
free(hdr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_AP || HOSTAPD */
|
||||
|
||||
#ifdef CONFIG_AP
|
||||
|
@ -3094,9 +3164,6 @@ static int wpa_driver_nl80211_set_operstate(void *priv, int state)
|
|||
|
||||
#ifdef HOSTAPD
|
||||
|
||||
static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
||||
|
||||
|
||||
static struct i802_bss * get_bss(struct wpa_driver_nl80211_data *drv,
|
||||
int ifindex)
|
||||
{
|
||||
|
@ -3450,73 +3517,6 @@ static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,
|
|||
}
|
||||
|
||||
|
||||
static int i802_send_eapol(void *priv, const u8 *addr, const u8 *data,
|
||||
size_t data_len, int encrypt, const u8 *own_addr)
|
||||
{
|
||||
struct wpa_driver_nl80211_data *drv = priv;
|
||||
struct ieee80211_hdr *hdr;
|
||||
size_t len;
|
||||
u8 *pos;
|
||||
int res;
|
||||
#if 0 /* FIX */
|
||||
int qos = sta->flags & WLAN_STA_WME;
|
||||
#else
|
||||
int qos = 0;
|
||||
#endif
|
||||
|
||||
len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
|
||||
data_len;
|
||||
hdr = os_zalloc(len);
|
||||
if (hdr == NULL) {
|
||||
printf("malloc() failed for i802_send_data(len=%lu)\n",
|
||||
(unsigned long) len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdr->frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
|
||||
hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
|
||||
if (encrypt)
|
||||
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
|
||||
#if 0 /* To be enabled if qos determination is added above */
|
||||
if (qos) {
|
||||
hdr->frame_control |=
|
||||
host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
|
||||
memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
|
||||
memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
|
||||
pos = (u8 *) (hdr + 1);
|
||||
|
||||
#if 0 /* To be enabled if qos determination is added above */
|
||||
if (qos) {
|
||||
/* add an empty QoS header if needed */
|
||||
pos[0] = 0;
|
||||
pos[1] = 0;
|
||||
pos += 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
|
||||
pos += sizeof(rfc1042_header);
|
||||
WPA_PUT_BE16(pos, ETH_P_PAE);
|
||||
pos += 2;
|
||||
memcpy(pos, data, data_len);
|
||||
|
||||
res = wpa_driver_nl80211_send_frame(drv, (u8 *) hdr, len, encrypt);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
|
||||
"failed: %d (%s)",
|
||||
(unsigned long) len, errno, strerror(errno));
|
||||
}
|
||||
free(hdr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int i802_sta_set_flags(void *priv, const u8 *addr,
|
||||
int total_flags, int flags_or, int flags_and)
|
||||
{
|
||||
|
@ -3969,6 +3969,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|||
.get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data,
|
||||
.sta_add = wpa_driver_nl80211_sta_add,
|
||||
.sta_remove = wpa_driver_nl80211_sta_remove,
|
||||
.hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
|
||||
#endif /* CONFIG_AP || HOSTAPD */
|
||||
#ifdef HOSTAPD
|
||||
.hapd_init = i802_init,
|
||||
|
@ -3977,7 +3978,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|||
.get_seqnum = i802_get_seqnum,
|
||||
.flush = i802_flush,
|
||||
.read_sta_data = i802_read_sta_data,
|
||||
.hapd_send_eapol = i802_send_eapol,
|
||||
.sta_set_flags = i802_sta_set_flags,
|
||||
.sta_deauth = i802_sta_deauth,
|
||||
.sta_disassoc = i802_sta_disassoc,
|
||||
|
|
|
@ -248,6 +248,17 @@ static struct hostapd_hw_modes *ap_driver_get_hw_feature_data(void *priv,
|
|||
}
|
||||
|
||||
|
||||
static int ap_driver_hapd_send_eapol(void *priv, const u8 *addr,
|
||||
const u8 *data, size_t data_len,
|
||||
int encrypt, const u8 *own_addr)
|
||||
{
|
||||
struct ap_driver_data *drv = priv;
|
||||
struct wpa_supplicant *wpa_s = drv->hapd->iface->owner;
|
||||
return wpa_drv_hapd_send_eapol(wpa_s, addr, data, data_len, encrypt,
|
||||
own_addr);
|
||||
}
|
||||
|
||||
|
||||
struct wpa_driver_ops ap_driver_ops =
|
||||
{
|
||||
.name = "wpa_supplicant",
|
||||
|
@ -273,6 +284,7 @@ struct wpa_driver_ops ap_driver_ops =
|
|||
.set_short_slot_time = ap_driver_set_short_slot_time,
|
||||
.set_tx_queue_params = ap_driver_set_tx_queue_params,
|
||||
.get_hw_feature_data = ap_driver_get_hw_feature_data,
|
||||
.hapd_send_eapol = ap_driver_hapd_send_eapol,
|
||||
};
|
||||
|
||||
|
||||
|
@ -486,3 +498,10 @@ void ap_mgmt_tx_cb(void *ctx, u8 *buf, size_t len, u16 stype, int ok)
|
|||
ieee802_11_mgmt_cb(wpa_s->ap_iface->bss[0], buf, len, stype, ok);
|
||||
}
|
||||
#endif /* NEED_MLME */
|
||||
|
||||
|
||||
void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
|
||||
const u8 *src_addr, const u8 *buf, size_t len)
|
||||
{
|
||||
hostapd_eapol_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len);
|
||||
}
|
||||
|
|
|
@ -19,5 +19,7 @@
|
|||
int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid);
|
||||
void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s);
|
||||
void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
|
||||
const u8 *src_addr, const u8 *buf, size_t len);
|
||||
|
||||
#endif /* AP_H */
|
||||
|
|
|
@ -415,4 +415,16 @@ static inline int wpa_drv_sta_remove(struct wpa_supplicant *wpa_s,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static inline int wpa_drv_hapd_send_eapol(struct wpa_supplicant *wpa_s,
|
||||
const u8 *addr, const u8 *data,
|
||||
size_t data_len, int encrypt,
|
||||
const u8 *own_addr)
|
||||
{
|
||||
if (wpa_s->driver->hapd_send_eapol)
|
||||
return wpa_s->driver->hapd_send_eapol(wpa_s->drv_priv, addr,
|
||||
data, data_len, encrypt,
|
||||
own_addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* DRIVER_I_H */
|
||||
|
|
|
@ -1570,6 +1570,13 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
|
|||
wpa_printf(MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
|
||||
wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
|
||||
|
||||
#ifdef CONFIG_AP
|
||||
if (wpa_s->ap_iface) {
|
||||
wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_AP */
|
||||
|
||||
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
|
||||
wpa_printf(MSG_DEBUG, "Ignored received EAPOL frame since "
|
||||
"no key management is configured");
|
||||
|
|
Loading…
Reference in a new issue