diff --git a/src/netdev.c b/src/netdev.c index 990e9639..f3266c83 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -29,11 +29,14 @@ #include #include #include +#include + #include #include "linux/nl80211.h" #include "src/wiphy.h" #include "src/device.h" +#include "src/scan.h" #include "src/netdev.h" struct netdev { @@ -41,6 +44,10 @@ struct netdev { char name[IFNAMSIZ]; uint32_t type; uint8_t addr[ETH_ALEN]; + + netdev_event_func_t event_filter; + netdev_connect_cb_t connect_cb; + void *user_data; }; static struct l_netlink *rtnl = NULL; @@ -160,6 +167,64 @@ struct netdev *netdev_find(int ifindex) return l_queue_find(netdev_list, netdev_match, L_UINT_TO_PTR(ifindex)); } +static void netdev_cmd_authenticate_cb(struct l_genl_msg *msg, void *user_data) +{ + struct netdev *netdev = user_data; + + if (l_genl_msg_get_error(msg) >= 0) { + if (netdev->event_filter) + netdev->event_filter(netdev, + NETDEV_EVENT_AUTHENTICATING, + netdev->user_data); + + return; + } + + if (netdev->connect_cb) + netdev->connect_cb(netdev, NETDEV_RESULT_AUTHENTICATION_FAILED, + netdev->user_data); +} + +static struct l_genl_msg *netdev_build_cmd_authenticate(struct netdev *netdev, + struct scan_bss *bss) +{ + uint32_t auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; + struct l_genl_msg *msg; + + msg = l_genl_msg_new_sized(NL80211_CMD_AUTHENTICATE, 512); + l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index); + l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ, + 4, &bss->frequency); + l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, bss->addr); + l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, + bss->ssid_len, bss->ssid); + l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type); + + return msg; +} + +int netdev_connect(struct netdev *netdev, struct scan_bss *bss, + struct eapol_sm *sm, + netdev_event_func_t event_filter, + netdev_connect_cb_t cb, void *user_data) +{ + struct l_genl_msg *authenticate; + + authenticate = netdev_build_cmd_authenticate(netdev, bss); + if (!authenticate) + return -EINVAL; + + if (!l_genl_family_send(nl80211, authenticate, + netdev_cmd_authenticate_cb, netdev, NULL)) + return -EIO; + + netdev->event_filter = event_filter; + netdev->connect_cb = cb; + netdev->user_data = user_data; + + return 0; +} + static void netdev_get_interface_callback(struct l_genl_msg *msg, void *user_data) { diff --git a/src/netdev.h b/src/netdev.h index fa47862a..ea31974f 100644 --- a/src/netdev.h +++ b/src/netdev.h @@ -23,8 +23,32 @@ #include struct netdev; +struct scan_bss; +struct eapol_sm *sm; + +enum netdev_result { + NETDEV_RESULT_OK, + NETDEV_RESULT_AUTHENTICATION_FAILED, + NETDEV_RESULT_ASSOCIATION_FAILED, + NETDEV_RESULT_HANDSHAKE_FAILED, + NETDEV_RESULT_KEY_SETTING_FAILED, +}; + +enum netdev_event { + NETDEV_EVENT_AUTHENTICATING, + NETDEV_EVENT_ASSOCIATING, + NETDEV_EVENT_4WAY_HANDSHAKE, + NETDEV_EVENT_SETTING_KEYS, + NETDEV_EVENT_LOST_BEACON, +}; typedef void (*netdev_command_func_t) (bool result, void *user_data); +typedef void (*netdev_connect_cb_t)(struct netdev *netdev, + enum netdev_result result, + void *user_data); +typedef void (*netdev_event_func_t)(struct netdev *netdev, + enum netdev_event event, + void *user_data); void netdev_set_linkmode_and_operstate(uint32_t ifindex, uint8_t linkmode, uint8_t operstate, @@ -35,6 +59,11 @@ uint32_t netdev_get_ifindex(struct netdev *netdev); uint32_t netdev_get_iftype(struct netdev *netdev); const char *netdev_get_name(struct netdev *netdev); +int netdev_connect(struct netdev *netdev, struct scan_bss *bss, + struct eapol_sm *sm, + netdev_event_func_t event_filter, + netdev_connect_cb_t cb, void *user_data); + struct netdev *netdev_find(int ifindex); bool netdev_init(struct l_genl_family *in);