From a2be179f574ea689f464c0b59a4f884f32ab7683 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Mon, 22 Jun 2015 17:02:52 -0500 Subject: [PATCH] wiphy: Add netdev state machine --- src/wiphy.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/src/wiphy.c b/src/wiphy.c index d920483a..2735134d 100644 --- a/src/wiphy.c +++ b/src/wiphy.c @@ -64,11 +64,20 @@ struct network { bool ask_psk:1; /* Whether we should force-ask agent for PSK */ }; +enum netdev_state { + NETDEV_STATE_DISCONNECTED = 0, /* Disconnected, no auto-connect */ + NETDEV_STATE_AUTOCONNECT, /* Disconnected, try auto-connect */ + NETDEV_STATE_CONNECTING, /* Connecting */ + NETDEV_STATE_CONNECTED, + NETDEV_STATE_DISCONNECTING, +}; + struct netdev { uint32_t index; char name[IFNAMSIZ]; uint32_t type; uint8_t addr[ETH_ALEN]; + enum netdev_state state; struct l_queue *bss_list; struct l_queue *old_bss_list; struct l_dbus_message *scan_pending; @@ -196,6 +205,49 @@ static struct l_dbus_message *network_get_properties(struct l_dbus *dbus, return reply; } +static const char *netdev_state_to_string(enum netdev_state state) +{ + switch (state) { + case NETDEV_STATE_DISCONNECTED: + return "disconnected"; + case NETDEV_STATE_AUTOCONNECT: + return "autoconnect"; + case NETDEV_STATE_CONNECTING: + return "connecting"; + case NETDEV_STATE_CONNECTED: + return "connected"; + case NETDEV_STATE_DISCONNECTING: + return "disconnecting"; + } + + return "invalid"; +} + +static void netdev_enter_state(struct netdev *netdev, enum netdev_state state) +{ + l_debug("Old State: %s, new state: %s", + netdev_state_to_string(netdev->state), + netdev_state_to_string(state)); + + switch (state) { + case NETDEV_STATE_AUTOCONNECT: + scan_periodic_start(netdev->index); + break; + case NETDEV_STATE_DISCONNECTED: + scan_periodic_stop(netdev->index); + break; + case NETDEV_STATE_CONNECTED: + scan_periodic_stop(netdev->index); + break; + case NETDEV_STATE_CONNECTING: + break; + case NETDEV_STATE_DISCONNECTING: + break; + } + + netdev->state = state; +} + static void netdev_disassociated(struct netdev *netdev) { struct network *network = netdev->connected_network; @@ -205,6 +257,8 @@ static void netdev_disassociated(struct netdev *netdev) netdev->connected_bss = NULL; netdev->connected_network = NULL; + + netdev_enter_state(netdev, NETDEV_STATE_AUTOCONNECT); } static void netdev_lost_beacon(struct netdev *netdev) @@ -297,6 +351,7 @@ static int mlme_authenticate_cmd(struct network *network, struct scan_bss *bss) netdev->connected_bss = bss; netdev->connected_network = network; + netdev_enter_state(netdev, NETDEV_STATE_CONNECTING); return 0; } @@ -419,7 +474,8 @@ static struct l_dbus_message *network_connect(struct l_dbus *dbus, l_debug(""); - if (netdev->connect_pending) + if (netdev->state != NETDEV_STATE_DISCONNECTED && + netdev->state != NETDEV_STATE_AUTOCONNECT) return dbus_error_busy(message); /* @@ -756,7 +812,8 @@ static struct l_dbus_message *device_disconnect(struct l_dbus *dbus, l_debug(""); - if (netdev->connect_pending) + if (netdev->state == NETDEV_STATE_CONNECTING || + netdev->state == NETDEV_STATE_DISCONNECTING) return dbus_error_busy(message); if (!netdev->connected_bss) @@ -773,6 +830,8 @@ static struct l_dbus_message *device_disconnect(struct l_dbus *dbus, netdev->connected_bss->addr); l_genl_family_send(nl80211, msg, genl_disconnect_cb, netdev, NULL); + netdev_enter_state(netdev, NETDEV_STATE_DISCONNECTING); + netdev->disconnect_pending = l_dbus_message_ref(message); return NULL; @@ -922,6 +981,7 @@ static void setting_keys_failed(struct netdev *netdev, uint16_t reason_code) msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, netdev->connected_bss->addr); l_genl_family_send(nl80211, msg, deauthenticate_cb, netdev, NULL); + netdev_enter_state(netdev, NETDEV_STATE_DISCONNECTING); } static void handshake_failed(uint32_t ifindex, @@ -938,6 +998,7 @@ static void handshake_failed(uint32_t ifindex, msg_append_attr(msg, NL80211_ATTR_REASON_CODE, 2, &reason_code); msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, aa); l_genl_family_send(nl80211, msg, deauthenticate_cb, netdev, NULL); + netdev_enter_state(netdev, NETDEV_STATE_DISCONNECTING); } static void mlme_set_pairwise_key_cb(struct l_genl_msg *msg, void *data) @@ -1097,6 +1158,8 @@ static void operstate_cb(bool result, void *user_data) l_dbus_message_set_arguments(reply, ""); dbus_pending_reply(&netdev->connect_pending, reply); } + + netdev_enter_state(netdev, NETDEV_STATE_CONNECTED); } static void set_station_cb(struct l_genl_msg *msg, void *user_data) @@ -1746,6 +1809,8 @@ static void interface_dump_callback(struct l_genl_msg *msg, void *user_data) netdev_set_linkmode_and_operstate(netdev->index, 1, IF_OPER_DORMANT, NULL, NULL); + + netdev_enter_state(netdev, NETDEV_STATE_AUTOCONNECT); } l_debug("Found interface %s", netdev->name);