From 016cca4c6be704b306db9551c1f7cb2a91348938 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 3 Jul 2008 09:46:23 +0200 Subject: [PATCH] Rewrite supplicant support for new element infrastructure --- plugins/Makefile.am | 2 +- plugins/supplicant.c | 171 ++++++++++++----------------- plugins/supplicant.h | 28 +++-- plugins/wifi.c | 298 +++------------------------------------------------ 4 files changed, 105 insertions(+), 394 deletions(-) diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 37ee862..66daf5d 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -10,7 +10,7 @@ hal_la_CFLAGS = @GLIB_CFLAGS@ @HAL_CFLAGS@ ethernet_la_SOURCES = ethernet.c -wifi_la_SOURCES = wifi.c +wifi_la_SOURCES = wifi.c supplicant.h supplicant.c bluetooth_la_SOURCES = bluetooth.c diff --git a/plugins/supplicant.c b/plugins/supplicant.c index cba93cd..d387c95 100644 --- a/plugins/supplicant.c +++ b/plugins/supplicant.c @@ -23,23 +23,17 @@ #include #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - +#include #include -#include #include #include "supplicant.h" +#define IEEE80211_CAP_ESS 0x0001 +#define IEEE80211_CAP_IBSS 0x0002 +#define IEEE80211_CAP_PRIVACY 0x0010 + enum supplicant_state { STATE_INACTIVE, STATE_SCANNING, @@ -55,36 +49,25 @@ struct supplicant_task { DBusConnection *conn; int ifindex; gchar *ifname; - struct connman_iface *iface; + struct connman_element *element; + struct supplicant_callback *callback; gchar *path; gboolean created; gchar *network; enum supplicant_state state; }; -static GSList *tasks = NULL; +static GStaticMutex task_mutex = G_STATIC_MUTEX_INIT; +static GSList *task_list = NULL; -struct supplicant_ap { - gchar *identifier; - GByteArray *ssid; - guint capabilities; - gboolean has_wep; - gboolean has_wpa; - gboolean has_rsn; -}; - -#define IEEE80211_CAP_ESS 0x0001 -#define IEEE80211_CAP_IBSS 0x0002 -#define IEEE80211_CAP_PRIVACY 0x0010 - -static struct supplicant_task *find_task(int ifindex) +static struct supplicant_task *find_task_by_index(int index) { GSList *list; - for (list = tasks; list; list = list->next) { + for (list = task_list; list; list = list->next) { struct supplicant_task *task = list->data; - if (task->ifindex == ifindex) + if (task->ifindex == index) return task; } @@ -606,7 +589,8 @@ static int initiate_scan(struct supplicant_task *task) return 0; } -static void extract_ssid(struct supplicant_ap *ap, DBusMessageIter *value) +static void extract_ssid(struct supplicant_network *network, + DBusMessageIter *value) { DBusMessageIter array; unsigned char *ssid; @@ -615,10 +599,11 @@ static void extract_ssid(struct supplicant_ap *ap, DBusMessageIter *value) dbus_message_iter_recurse(value, &array); dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len); - ap->identifier = g_strdup((char *) ssid); + network->identifier = g_strdup((char *) ssid); } -static void extract_wpaie(struct supplicant_ap *ap, DBusMessageIter *value) +static void extract_wpaie(struct supplicant_network *network, + DBusMessageIter *value) { DBusMessageIter array; unsigned char *ie; @@ -628,10 +613,11 @@ static void extract_wpaie(struct supplicant_ap *ap, DBusMessageIter *value) dbus_message_iter_get_fixed_array(&array, &ie, &ie_len); if (ie_len > 0) - ap->has_wpa = TRUE; + network->has_wpa = TRUE; } -static void extract_rsnie(struct supplicant_ap *ap, DBusMessageIter *value) +static void extract_rsnie(struct supplicant_network *network, + DBusMessageIter *value) { DBusMessageIter array; unsigned char *ie; @@ -641,31 +627,30 @@ static void extract_rsnie(struct supplicant_ap *ap, DBusMessageIter *value) dbus_message_iter_get_fixed_array(&array, &ie, &ie_len); if (ie_len > 0) - ap->has_rsn = TRUE; + network->has_rsn = TRUE; } -static void extract_capabilites(struct supplicant_ap *ap, +static void extract_capabilites(struct supplicant_network *network, DBusMessageIter *value) { guint capabilities; dbus_message_iter_get_basic(value, &capabilities); - ap->capabilities = capabilities; + network->capabilities = capabilities; if (capabilities & IEEE80211_CAP_PRIVACY) - ap->has_wep = TRUE; + network->has_wep = TRUE; } static int parse_network_properties(struct supplicant_task *task, DBusMessage *message) { DBusMessageIter array, dict; - struct supplicant_ap *ap; - int security = 0; + struct supplicant_network *network; - ap = g_try_new0(struct supplicant_ap, 1); - if (ap == NULL) + network = g_try_new0(struct supplicant_network, 1); + if (network == NULL) return -ENOMEM; dbus_message_iter_init(message, &array); @@ -687,28 +672,21 @@ static int parse_network_properties(struct supplicant_task *task, //dbus_message_iter_get_basic(&value, &val); if (g_str_equal(key, "ssid") == TRUE) - extract_ssid(ap, &value); + extract_ssid(network, &value); else if (g_str_equal(key, "wpaie") == TRUE) - extract_wpaie(ap, &value); + extract_wpaie(network, &value); else if (g_str_equal(key, "rsnie") == TRUE) - extract_rsnie(ap, &value); + extract_rsnie(network, &value); else if (g_str_equal(key, "capabilities") == TRUE) - extract_capabilites(ap, &value); + extract_capabilites(network, &value); dbus_message_iter_next(&dict); } - if (ap->has_wep) - security |= 0x01; - if (ap->has_wpa) - security |= 0x02; - if (ap->has_rsn) - security |= 0x04; + if (task->callback && task->callback->scan_result) + task->callback->scan_result(task->element, network); - connman_iface_indicate_station(task->iface, - ap->identifier, 25, security); - - g_free(ap); + g_free(network); return 0; } @@ -843,10 +821,10 @@ static void state_change(struct supplicant_task *task, DBusMessage *msg) switch (task->state) { case STATE_COMPLETED: - connman_iface_indicate_carrier_on(task->iface); + /* carrier on */ break; case STATE_DISCONNECTED: - connman_iface_indicate_carrier_off(task->iface); + /* carrier off */ break; default: break; @@ -931,35 +909,22 @@ static int remove_filter(struct supplicant_task *task) return 0; } -int __supplicant_start(struct connman_iface *iface) +int __supplicant_start(struct connman_element *element, + struct supplicant_callback *callback) { - struct ifreq ifr; struct supplicant_task *task; - int sk, err; - - sk = socket(PF_INET, SOCK_DGRAM, 0); - if (sk < 0) - return -EIO; - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_ifindex = iface->index; - - err = ioctl(sk, SIOCGIFNAME, &ifr); - - close(sk); - - if (err < 0) - return -EIO; + int err; - DBG("interface %s", ifr.ifr_name); + DBG("element %p name %s", element, element->name); task = g_try_new0(struct supplicant_task, 1); if (task == NULL) return -ENOMEM; - task->ifindex = iface->index; - task->ifname = g_strdup(ifr.ifr_name); - task->iface = iface; + task->ifindex = element->netdev.index; + task->ifname = g_strdup(element->netdev.name); + task->element = element; + task->callback = callback; if (task->ifname == NULL) { g_free(task); @@ -973,6 +938,11 @@ int __supplicant_start(struct connman_iface *iface) } task->created = FALSE; + task->state = STATE_INACTIVE; + + g_static_mutex_lock(&task_mutex); + task_list = g_slist_append(task_list, task); + g_static_mutex_unlock(&task_mutex); err = get_interface(task); if (err < 0) { @@ -983,10 +953,6 @@ int __supplicant_start(struct connman_iface *iface) } } - task->state = STATE_INACTIVE; - - tasks = g_slist_append(tasks, task); - add_filter(task); set_ap_scan(task); @@ -994,17 +960,19 @@ int __supplicant_start(struct connman_iface *iface) return 0; } -int __supplicant_stop(struct connman_iface *iface) +int __supplicant_stop(struct connman_element *element) { struct supplicant_task *task; - task = find_task(iface->index); + DBG("element %p name %s", element, element->name); + + task = find_task_by_index(element->netdev.index); if (task == NULL) return -ENODEV; - DBG("interface %s", task->ifname); - - tasks = g_slist_remove(tasks, task); + g_static_mutex_lock(&task_mutex); + task_list = g_slist_remove(task_list, task); + g_static_mutex_unlock(&task_mutex); disable_network(task); @@ -1023,17 +991,17 @@ int __supplicant_stop(struct connman_iface *iface) return 0; } -int __supplicant_scan(struct connman_iface *iface) +int __supplicant_scan(struct connman_element *element) { struct supplicant_task *task; int err; - task = find_task(iface->index); + DBG("element %p name %s", element, element->name); + + task = find_task_by_index(element->netdev.index); if (task == NULL) return -ENODEV; - DBG("interface %s", task->ifname); - switch (task->state) { case STATE_SCANNING: return -EALREADY; @@ -1051,39 +1019,38 @@ int __supplicant_scan(struct connman_iface *iface) return 0; } -int __supplicant_connect(struct connman_iface *iface, - const char *network, const char *passphrase) +int __supplicant_connect(struct connman_element *element) { struct supplicant_task *task; - task = find_task(iface->index); + DBG("element %p name %s", element, element->name); + + task = find_task_by_index(element->netdev.index); if (task == NULL) return -ENODEV; - DBG("interface %s", task->ifname); - add_network(task); select_network(task); disable_network(task); - set_network(task, network, passphrase); + set_network(task, NULL, NULL); enable_network(task); return 0; } -int __supplicant_disconnect(struct connman_iface *iface) +int __supplicant_disconnect(struct connman_element *element) { struct supplicant_task *task; - task = find_task(iface->index); + DBG("element %p name %s", element, element->name); + + task = find_task_by_index(element->netdev.index); if (task == NULL) return -ENODEV; - DBG("interface %s", task->ifname); - disable_network(task); remove_network(task); diff --git a/plugins/supplicant.h b/plugins/supplicant.h index 1ef96d7..3ba062a 100644 --- a/plugins/supplicant.h +++ b/plugins/supplicant.h @@ -19,17 +19,31 @@ * */ -#include +#include #define SUPPLICANT_NAME "fi.epitest.hostap.WPASupplicant" #define SUPPLICANT_INTF "fi.epitest.hostap.WPASupplicant" #define SUPPLICANT_PATH "/fi/epitest/hostap/WPASupplicant" -int __supplicant_start(struct connman_iface *iface); -int __supplicant_stop(struct connman_iface *iface); +struct supplicant_network { + gchar *identifier; + GByteArray *ssid; + guint capabilities; + gboolean has_wep; + gboolean has_wpa; + gboolean has_rsn; +}; -int __supplicant_scan(struct connman_iface *iface); +struct supplicant_callback { + void (*scan_result) (struct connman_element *element, + struct supplicant_network *network); +}; -int __supplicant_connect(struct connman_iface *iface, - const char *network, const char *passphrase); -int __supplicant_disconnect(struct connman_iface *iface); +int __supplicant_start(struct connman_element *element, + struct supplicant_callback *callback); +int __supplicant_stop(struct connman_element *element); + +int __supplicant_scan(struct connman_element *element); + +int __supplicant_connect(struct connman_element *element); +int __supplicant_disconnect(struct connman_element *element); diff --git a/plugins/wifi.c b/plugins/wifi.c index 6ab5940..40a5913 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -23,300 +23,44 @@ #include #endif -#include - #include #include #include -static DBusConnection *connection; - -#define SUPPLICANT_NAME "fi.epitest.hostap.WPASupplicant" -#define SUPPLICANT_INTF "fi.epitest.hostap.WPASupplicant" -#define SUPPLICANT_PATH "/fi/epitest/hostap/WPASupplicant" - -enum supplicant_state { - STATE_INACTIVE, - STATE_SCANNING, - STATE_ASSOCIATING, - STATE_ASSOCIATED, - STATE_4WAY_HANDSHAKE, - STATE_GROUP_HANDSHAKE, - STATE_COMPLETED, - STATE_DISCONNECTED, -}; - -struct supplicant_task { - int ifindex; - gchar *ifname; - enum supplicant_state state; - gchar *path; - gboolean created; -}; - -static GStaticMutex task_mutex = G_STATIC_MUTEX_INIT; -static GSList *task_list = NULL; - -static struct supplicant_task *find_task_by_index(int index) -{ - GSList *list; - - for (list = task_list; list; list = list->next) { - struct supplicant_task *task = list->data; - - if (task->ifindex == index) - return task; - } +#include "supplicant.h" - return NULL; -} - -static int get_interface(struct supplicant_task *task) +static void scan_result(struct connman_element *element, + struct supplicant_network *network) { - DBusMessage *message, *reply; - DBusError error; - const char *path; - - DBG("task %p", task); - - message = dbus_message_new_method_call(SUPPLICANT_NAME, SUPPLICANT_PATH, - SUPPLICANT_INTF, "getInterface"); - if (message == NULL) - return -ENOMEM; - - dbus_message_append_args(message, DBUS_TYPE_STRING, &task->ifname, - DBUS_TYPE_INVALID); - - dbus_error_init(&error); - - reply = dbus_connection_send_with_reply_and_block(connection, - message, -1, &error); - if (reply == NULL) { - if (dbus_error_is_set(&error) == TRUE) { - connman_error("%s", error.message); - dbus_error_free(&error); - } else - connman_error("Failed to get interface"); - dbus_message_unref(message); - return -EIO; - } - - dbus_message_unref(message); - - dbus_error_init(&error); - - if (dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID) == FALSE) { - if (dbus_error_is_set(&error) == TRUE) { - connman_error("%s", error.message); - dbus_error_free(&error); - } else - connman_error("Wrong arguments for interface"); - dbus_message_unref(reply); - return -EIO; - } - - DBG("path %s", path); - - task->path = g_strdup(path); - task->created = FALSE; - - dbus_message_unref(reply); - - return 0; -} - -static int add_interface(struct supplicant_task *task) -{ - DBusMessage *message, *reply; - DBusError error; - const char *path; - - DBG("task %p", task); - - message = dbus_message_new_method_call(SUPPLICANT_NAME, SUPPLICANT_PATH, - SUPPLICANT_INTF, "addInterface"); - if (message == NULL) - return -ENOMEM; - - dbus_error_init(&error); - - dbus_message_append_args(message, DBUS_TYPE_STRING, &task->ifname, - DBUS_TYPE_INVALID); - - reply = dbus_connection_send_with_reply_and_block(connection, - message, -1, &error); - if (reply == NULL) { - if (dbus_error_is_set(&error) == TRUE) { - connman_error("%s", error.message); - dbus_error_free(&error); - } else - connman_error("Failed to add interface"); - dbus_message_unref(message); - return -EIO; - } - - dbus_message_unref(message); - - dbus_error_init(&error); - - if (dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID) == FALSE) { - if (dbus_error_is_set(&error) == TRUE) { - connman_error("%s", error.message); - dbus_error_free(&error); - } else - connman_error("Wrong arguments for interface"); - dbus_message_unref(reply); - return -EIO; - } - - DBG("path %s", path); - - task->path = g_strdup(path); - task->created = TRUE; - - dbus_message_unref(reply); - - return 0; -} - -static int remove_interface(struct supplicant_task *task) -{ - DBusMessage *message, *reply; - DBusError error; - - DBG("task %p", task); - - if (task->created == FALSE) - return -EINVAL; - - message = dbus_message_new_method_call(SUPPLICANT_NAME, SUPPLICANT_PATH, - SUPPLICANT_INTF, "removeInterface"); - if (message == NULL) - return -ENOMEM; - - dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &task->path, - DBUS_TYPE_INVALID); - - dbus_error_init(&error); - - reply = dbus_connection_send_with_reply_and_block(connection, - message, -1, &error); - if (reply == NULL) { - if (dbus_error_is_set(&error) == TRUE) { - connman_error("%s", error.message); - dbus_error_free(&error); - } else - connman_error("Failed to remove interface"); - dbus_message_unref(message); - return -EIO; - } - - dbus_message_unref(message); - - g_free(task->path); - task->path = NULL; - - dbus_message_unref(reply); + DBG("element %p name %s", element, element->name); - return 0; + DBG("network %p identifier %s", network, network->identifier); } -static int initiate_scan(struct supplicant_task *task) -{ - DBusMessage *message, *reply; - DBusError error; - - DBG("task %p", task); - - message = dbus_message_new_method_call(SUPPLICANT_NAME, task->path, - SUPPLICANT_INTF ".Interface", "scan"); - if (message == NULL) - return -ENOMEM; - - dbus_error_init(&error); - - reply = dbus_connection_send_with_reply_and_block(connection, - message, -1, &error); - if (reply == NULL) { - if (dbus_error_is_set(&error) == TRUE) { - connman_error("%s", error.message); - dbus_error_free(&error); - } else - connman_error("Failed to initiate scan"); - dbus_message_unref(message); - return -EIO; - } - - dbus_message_unref(message); - - dbus_message_unref(reply); - - return 0; -} +static struct supplicant_callback wifi_callback = { + .scan_result = scan_result, +}; static int wifi_probe(struct connman_element *element) { - struct supplicant_task *task; int err; DBG("element %p name %s", element, element->name); - task = g_try_new0(struct supplicant_task, 1); - if (task == NULL) - return -ENOMEM; - - task->ifindex = element->netdev.index; - task->ifname = g_strdup(element->netdev.name); - - if (task->ifname == NULL) { - g_free(task); - return -ENOMEM; - } - - task->created = FALSE; - task->state = STATE_INACTIVE; - - g_static_mutex_lock(&task_mutex); - task_list = g_slist_append(task_list, task); - g_static_mutex_unlock(&task_mutex); - - err = get_interface(task); - if (err < 0) { - err = add_interface(task); - if (err < 0) { - g_free(task); - return err; - } - } + err = __supplicant_start(element, &wifi_callback); + if (err < 0) + return err; - initiate_scan(task); + __supplicant_scan(element); return 0; } static void wifi_remove(struct connman_element *element) { - struct supplicant_task *task; - DBG("element %p name %s", element, element->name); - g_static_mutex_lock(&task_mutex); - task = find_task_by_index(element->netdev.index); - g_static_mutex_unlock(&task_mutex); - - if (task == NULL) - return; - - g_static_mutex_lock(&task_mutex); - task_list = g_slist_remove(task_list, task); - g_static_mutex_unlock(&task_mutex); - - remove_interface(task); - - g_free(task->ifname); - g_free(task); + __supplicant_stop(element); } static struct connman_driver wifi_driver = { @@ -329,26 +73,12 @@ static struct connman_driver wifi_driver = { static int wifi_init(void) { - int err; - - connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - if (connection == NULL) - return -EIO; - - err = connman_driver_register(&wifi_driver); - if (err < 0) { - dbus_connection_unref(connection); - return err; - } - - return 0; + return connman_driver_register(&wifi_driver); } static void wifi_exit(void) { connman_driver_unregister(&wifi_driver); - - dbus_connection_unref(connection); } CONNMAN_PLUGIN_DEFINE("WiFi", "WiFi interface plugin", VERSION, -- 2.7.4