diff --git a/src/netdev.c b/src/netdev.c index 34ccbdb2..1229dab5 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include @@ -38,6 +38,7 @@ #include "src/iwd.h" #include "src/wiphy.h" #include "src/ie.h" +#include "src/mpdu.h" #include "src/eapol.h" #include "src/crypto.h" #include "src/device.h" @@ -55,6 +56,7 @@ struct netdev { void *user_data; struct l_genl_msg *associate_msg; struct eapol_sm *sm; + uint8_t remote_addr[ETH_ALEN]; }; static struct l_netlink *rtnl = NULL; @@ -191,6 +193,76 @@ static void netdev_deauthenticate_event(struct l_genl_msg *msg, l_debug(""); } +static struct l_genl_msg *netdev_build_cmd_deauthenticate(struct netdev *netdev, + uint16_t reason_code) +{ + struct l_genl_msg *msg; + + msg = l_genl_msg_new_sized(NL80211_CMD_DEAUTHENTICATE, 128); + l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index); + l_genl_msg_append_attr(msg, NL80211_ATTR_REASON_CODE, 2, &reason_code); + l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, + netdev->remote_addr); + + return msg; +} + +static void netdev_operstate_cb(bool success, void *user_data) +{ + struct netdev *netdev = user_data; + enum netdev_result result; + + if (!success) { + struct l_genl_msg *msg; + + l_error("Setting LinkMode and OperState failed for ifindex: %d", + netdev->index); + + msg = netdev_build_cmd_deauthenticate(netdev, + MPDU_REASON_CODE_UNSPECIFIED); + l_genl_family_send(nl80211, msg, NULL, NULL, NULL); + + result = NETDEV_RESULT_KEY_SETTING_FAILED; + } else + result = NETDEV_RESULT_OK; + + if (netdev->connect_cb) + netdev->connect_cb(netdev, result, netdev->user_data); +} + +static void netdev_associate_event(struct l_genl_msg *msg, + struct netdev *netdev) +{ + int err; + + l_debug(""); + + err = l_genl_msg_get_error(msg); + if (err < 0) { + l_error("association failed %s (%d)", strerror(-err), err); + goto error; + } + + if (netdev->sm) { + eapol_start(netdev->index, netdev->sm); + netdev->sm = NULL; + + if (netdev->event_filter) + netdev->event_filter(netdev, + NETDEV_EVENT_4WAY_HANDSHAKE, + netdev->user_data); + } else + netdev_set_linkmode_and_operstate(netdev->index, 1, IF_OPER_UP, + netdev_operstate_cb, netdev); + + return; + +error: + if (netdev->connect_cb) + netdev->connect_cb(netdev, NETDEV_RESULT_ASSOCIATION_FAILED, + netdev->user_data); +} + static void netdev_cmd_associate_cb(struct l_genl_msg *msg, void *user_data) { struct netdev *netdev = user_data; @@ -202,11 +274,6 @@ static void netdev_cmd_associate_cb(struct l_genl_msg *msg, void *user_data) NETDEV_EVENT_ASSOCIATING, netdev->user_data); - if (netdev->sm) { - eapol_start(netdev->index, netdev->sm); - netdev->sm = NULL; - } - return; } @@ -377,6 +444,7 @@ int netdev_connect(struct netdev *netdev, struct scan_bss *bss, netdev->user_data = user_data; netdev->sm = sm; netdev->associate_msg = associate; + memcpy(netdev->remote_addr, bss->addr, ETH_ALEN); return 0; } @@ -427,6 +495,9 @@ static void netdev_mlme_notify(struct l_genl_msg *msg, void *user_data) case NL80211_CMD_DEAUTHENTICATE: netdev_deauthenticate_event(msg, netdev); break; + case NL80211_CMD_ASSOCIATE: + netdev_associate_event(msg, netdev); + break; } } diff --git a/src/wiphy.c b/src/wiphy.c index 22d4823c..11779ea8 100644 --- a/src/wiphy.c +++ b/src/wiphy.c @@ -814,28 +814,6 @@ static void wiphy_set_gtk(uint32_t ifindex, uint8_t key_index, gtk_buf, gtk_len, rsc, rsc_len); } -static void mlme_associate_event(struct l_genl_msg *msg, struct device *device) -{ - int err; - - l_debug(""); - - err = l_genl_msg_get_error(msg); - if (err < 0) { - l_error("association failed %s (%d)", strerror(-err), err); - dbus_pending_reply(&device->connect_pending, - dbus_error_failed(device->connect_pending)); - device_disassociated(device); - return; - } - - l_info("Association completed"); - - if (network_get_security(device->connected_network) == SECURITY_NONE) - netdev_set_linkmode_and_operstate(device->index, 1, IF_OPER_UP, - operstate_cb, device); -} - static void mlme_disconnect_event(struct l_genl_msg *msg, struct device *device) { @@ -1531,9 +1509,6 @@ static void wiphy_mlme_notify(struct l_genl_msg *msg, void *user_data) switch (cmd) { - case NL80211_CMD_ASSOCIATE: - mlme_associate_event(msg, device); - break; case NL80211_CMD_DISCONNECT: mlme_disconnect_event(msg, device); break;