3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-17 17:39:28 +01:00

netdev: Move eapol_read to eapol.c

This commit is contained in:
Denis Kenzior 2016-06-28 16:58:17 -05:00
parent 746b0e5cb1
commit efe5bed7c5
3 changed files with 90 additions and 58 deletions

View File

@ -603,6 +603,7 @@ struct eapol_sm {
void *user_data;
void *tx_user_data;
struct l_timeout *timeout;
struct l_io *io;
bool have_snonce:1;
bool have_replay:1;
bool ptk_complete:1;
@ -619,6 +620,7 @@ static void eapol_sm_destroy(void *value)
l_free(sm->own_ie);
l_timeout_remove(sm->timeout);
l_io_destroy(sm->io);
if (sm->eap)
eap_free(sm->eap);
@ -1462,14 +1464,12 @@ void eapol_sm_set_8021x_config(struct eapol_sm *sm, struct l_settings *settings)
eap_load_settings(sm->eap, settings, "EAP-");
}
void __eapol_rx_packet(uint32_t ifindex, const uint8_t *spa, const uint8_t *aa,
const uint8_t *frame, size_t len)
static void eapol_rx_packet(struct eapol_sm *sm,
const uint8_t *frame, size_t len)
{
const struct eapol_header *eh;
struct eapol_sm *sm;
/* Validate Header */
if (len < sizeof(struct eapol_header))
return;
@ -1482,10 +1482,6 @@ void __eapol_rx_packet(uint32_t ifindex, const uint8_t *spa, const uint8_t *aa,
if (len < (size_t) 4 + L_BE16_TO_CPU(eh->packet_len))
return;
sm = eapol_find_sm(ifindex, spa, aa);
if (!sm)
return;
switch (eh->packet_type) {
case 0: /* EAPOL-EAP */
if (!sm->eap) {
@ -1512,7 +1508,7 @@ void __eapol_rx_packet(uint32_t ifindex, const uint8_t *spa, const uint8_t *aa,
if (!sm->have_pmk)
return;
eapol_key_handle(sm, ifindex, frame, len);
eapol_key_handle(sm, sm->ifindex, frame, len);
break;
default:
@ -1520,6 +1516,17 @@ void __eapol_rx_packet(uint32_t ifindex, const uint8_t *spa, const uint8_t *aa,
}
}
void __eapol_rx_packet(uint32_t ifindex, const uint8_t *spa, const uint8_t *aa,
const uint8_t *frame, size_t len)
{
struct eapol_sm *sm = eapol_find_sm(ifindex, spa, aa);
if (!sm)
return;
eapol_rx_packet(sm, frame, len);
}
void __eapol_update_replay_counter(uint32_t ifindex, const uint8_t *spa,
const uint8_t *aa, uint64_t replay_counter)
{
@ -1608,6 +1615,33 @@ struct l_io *eapol_open_pae(uint32_t index)
return io;
}
static bool eapol_read(struct l_io *io, void *user_data)
{
struct eapol_sm *sm = user_data;
int fd = l_io_get_fd(io);
struct sockaddr_ll sll;
socklen_t sll_len;
ssize_t bytes;
uint8_t frame[2304]; /* IEEE Std 802.11 ch. 8.2.3 */
memset(&sll, 0, sizeof(sll));
sll_len = sizeof(sll);
bytes = recvfrom(fd, frame, sizeof(frame), 0,
(struct sockaddr *) &sll, &sll_len);
if (bytes <= 0) {
l_error("EAPoL read socket: %s", strerror(errno));
return false;
}
if (memcmp(sm->aa, sll.sll_addr, 6))
return true;
eapol_rx_packet(sm, frame, bytes);
return true;
}
/*
* Default implementation of the frame transmission function.
* This function expects an fd to be passed as user_data
@ -1649,6 +1683,12 @@ void eapol_start(uint32_t ifindex, struct l_io *io, struct eapol_sm *sm)
{
sm->ifindex = ifindex;
sm->timeout = l_timeout_create(2, eapol_timeout, sm, NULL);
if (io) {
sm->io = io;
l_io_set_read_handler(io, eapol_read, sm, NULL);
}
l_queue_push_head(state_machines, sm);
}

View File

@ -202,7 +202,7 @@ const uint8_t *eapol_sm_get_own_ie(struct eapol_sm *sm, size_t *out_ie_len);
struct l_io *eapol_open_pae(uint32_t index);
void eapol_start(uint32_t ifindex, struct eapol_sm *sm);
void eapol_start(uint32_t ifindex, struct l_io *io, struct eapol_sm *sm);
void eapol_cancel(uint32_t ifindex);
bool eapol_init();

View File

@ -53,7 +53,6 @@ struct netdev {
char name[IFNAMSIZ];
uint32_t type;
uint8_t addr[ETH_ALEN];
struct l_io *eapol_io;
struct device *device;
netdev_event_func_t event_filter;
@ -62,6 +61,7 @@ struct netdev {
void *user_data;
struct l_genl_msg *associate_msg;
struct eapol_sm *sm;
struct l_io *eapol_io;
uint8_t remote_addr[ETH_ALEN];
uint32_t pairwise_new_key_cmd_id;
uint32_t pairwise_set_key_cmd_id;
@ -93,31 +93,6 @@ static void do_debug(const char *str, void *user_data)
l_info("%s%s", prefix, str);
}
static bool eapol_read(struct l_io *io, void *user_data)
{
struct netdev *netdev = user_data;
int fd = l_io_get_fd(io);
struct sockaddr_ll sll;
socklen_t sll_len;
ssize_t bytes;
uint8_t frame[2304]; /* IEEE Std 802.11 ch. 8.2.3 */
memset(&sll, 0, sizeof(sll));
sll_len = sizeof(sll);
bytes = recvfrom(fd, frame, sizeof(frame), 0,
(struct sockaddr *) &sll, &sll_len);
if (bytes <= 0) {
l_error("EAPoL read socket: %s", strerror(errno));
return false;
}
__eapol_rx_packet(netdev->index, netdev->addr, sll.sll_addr,
frame, bytes);
return true;
}
struct cb_data {
netdev_command_func_t callback;
void *user_data;
@ -233,6 +208,9 @@ static void netdev_free(void *data)
if (netdev->sm) {
eapol_sm_free(netdev->sm);
netdev->sm = NULL;
l_io_destroy(netdev->eapol_io);
netdev->eapol_io = NULL;
}
if (netdev->associate_msg) {
@ -240,9 +218,6 @@ static void netdev_free(void *data)
netdev->associate_msg = NULL;
}
l_io_destroy(netdev->eapol_io);
netdev->eapol_io = NULL;
netdev_set_linkmode_and_operstate(netdev->index, 0, IF_OPER_DOWN,
netdev_operstate_down_cb,
L_UINT_TO_PTR(netdev->index));
@ -838,6 +813,21 @@ static void netdev_set_rekey_offload(uint32_t ifindex,
}
static void netdev_connect_failed(struct netdev *netdev,
enum netdev_result result)
{
if (netdev->sm) {
eapol_sm_free(netdev->sm);
netdev->sm = NULL;
l_io_destroy(netdev->eapol_io);
netdev->eapol_io = NULL;
}
if (netdev->connect_cb)
netdev->connect_cb(netdev, result, netdev->user_data);
}
static void netdev_connect_event(struct l_genl_msg *msg,
struct netdev *netdev)
{
@ -873,9 +863,10 @@ static void netdev_connect_event(struct l_genl_msg *msg,
if (netdev->sm) {
eapol_sm_set_tx_user_data(netdev->sm,
L_INT_TO_PTR(l_io_get_fd(netdev->eapol_io)));
eapol_start(netdev->index, netdev->sm);
eapol_start(netdev->index, netdev->eapol_io, netdev->sm);
netdev->sm = NULL;
netdev->eapol_io = NULL;
if (netdev->event_filter)
netdev->event_filter(netdev,
@ -888,13 +879,7 @@ static void netdev_connect_event(struct l_genl_msg *msg,
return;
error:
if (netdev->sm) {
eapol_sm_free(netdev->sm);
netdev->sm = NULL;
if (netdev->connect_cb)
netdev->connect_cb(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
netdev->user_data);
netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED);
}
static void netdev_authenticate_event(struct l_genl_msg *msg,
@ -923,9 +908,7 @@ static void netdev_cmd_connect_cb(struct l_genl_msg *msg, void *user_data)
return;
}
if (netdev->connect_cb)
netdev->connect_cb(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
netdev->user_data);
netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED);
}
static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
@ -1003,9 +986,25 @@ int netdev_connect(struct netdev *netdev, struct scan_bss *bss,
netdev->event_filter = event_filter;
netdev->connect_cb = cb;
netdev->user_data = user_data;
netdev->sm = sm;
memcpy(netdev->remote_addr, bss->addr, ETH_ALEN);
netdev->sm = sm;
if (netdev->sm) {
/*
* Due to timing / race conditions, it is possible for
* EAPoL packets to arrive before the netdev events
* are received. Here we 'prime' the socket, so that
* the data is available as soon as we call eapol_start
*
* If this isn't done, then we might 'miss' the first EAPoL
* packet from the AP, and have to wait for the AP to
* retransmit. This delays our handshake by 1-2 seconds
*/
netdev->eapol_io = eapol_open_pae(netdev->index);
if (!netdev->eapol_io)
l_error("Failed to open PAE socket");
}
return 0;
}
@ -1259,13 +1258,6 @@ static void netdev_get_interface_callback(struct l_genl_msg *msg,
memcpy(netdev->addr, ifaddr, sizeof(netdev->addr));
memcpy(netdev->name, ifname, ifname_len);
netdev->eapol_io = eapol_open_pae(netdev->index);
if (netdev->eapol_io)
l_io_set_read_handler(netdev->eapol_io, eapol_read,
netdev, NULL);
else
l_error("Failed to open PAE socket");
l_queue_push_tail(netdev_list, netdev);
netdev_set_linkmode_and_operstate(netdev->index, 1,