summaryrefslogtreecommitdiff
path: root/tools/supplicant.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-12-29 04:07:06 -0800
committerMarcel Holtmann <marcel@holtmann.org>2009-12-29 04:07:06 -0800
commit3497514256cdbc94a7c72e4f48c1f38e7b1e559a (patch)
tree5627ffcb55cfca759759a0fda6872b71b743981f /tools/supplicant.c
parent13e490f8b49927898121d0949aee62913bbebed7 (diff)
downloadconnman-3497514256cdbc94a7c72e4f48c1f38e7b1e559a.tar.gz
connman-3497514256cdbc94a7c72e4f48c1f38e7b1e559a.tar.bz2
connman-3497514256cdbc94a7c72e4f48c1f38e7b1e559a.zip
Add interface and network handling to supplicant test program
Diffstat (limited to 'tools/supplicant.c')
-rw-r--r--tools/supplicant.c747
1 files changed, 637 insertions, 110 deletions
diff --git a/tools/supplicant.c b/tools/supplicant.c
index 4653a7f1..d9cd084f 100644
--- a/tools/supplicant.c
+++ b/tools/supplicant.c
@@ -30,182 +30,697 @@
#include <glib.h>
#include <gdbus.h>
+#include "supplicant-dbus.h"
#include "supplicant.h"
#define DBG(fmt, arg...) do { \
syslog(LOG_DEBUG, "%s() " fmt, __FUNCTION__ , ## arg); \
} while (0)
-#define SUPPLICANT_SERVICE "fi.w1.wpa_supplicant1"
-#define SUPPLICANT_INTERFACE "fi.w1.wpa_supplicant1"
-#define SUPPLICANT_PATH "/fi/w1/wpa_supplicant1"
-
#define TIMEOUT 5000
static DBusConnection *connection;
static const struct supplicant_callbacks *callbacks_pointer;
-static void show_property(const char *key, DBusMessageIter *iter)
-{
- DBusMessageIter array;
+static unsigned int eap_methods;
+
+static struct {
+ const char *str;
+ unsigned int val;
+} eap_method_map[] = {
+ { "MD5", SUPPLICANT_EAP_METHOD_MD5 },
+ { "TLS", SUPPLICANT_EAP_METHOD_TLS },
+ { "MSCHAPV2", SUPPLICANT_EAP_METHOD_MSCHAPV2 },
+ { "PEAP", SUPPLICANT_EAP_METHOD_PEAP },
+ { "TTLS", SUPPLICANT_EAP_METHOD_TTLS },
+ { "GTC", SUPPLICANT_EAP_METHOD_GTC },
+ { "OTP", SUPPLICANT_EAP_METHOD_OTP },
+ { "LEAP", SUPPLICANT_EAP_METHOD_LEAP },
+ { }
+};
+
+static struct {
const char *str;
- unsigned char byte;
+ unsigned int val;
+} scan_capa_map[] = {
+ { "active", SUPPLICANT_CAPABILITY_SCAN_ACTIVE },
+ { "passive", SUPPLICANT_CAPABILITY_SCAN_PASSIVE },
+ { "ssid", SUPPLICANT_CAPABILITY_SCAN_SSID },
+ { }
+};
+
+static GHashTable *interface_table;
+
+struct supplicant_interface {
+ char *path;
+ unsigned int scan_capa;
+ enum supplicant_state state;
+ dbus_bool_t scanning;
+ int apscan;
+ char *ifname;
+ char *driver;
+ char *bridge;
+ GHashTable *network_table;
+ GHashTable *bss_mapping;
+};
+
+struct supplicant_network {
+ struct supplicant_interface *interface;
+ char *group;
+ char *name;
+ enum supplicant_network_mode mode;
+ GHashTable *bss_table;
+};
+
+struct supplicant_bss {
+ struct supplicant_interface *interface;
+ char *path;
+ unsigned char bssid[6];
+ unsigned char ssid[32];
+ unsigned int ssid_len;
+ unsigned int frequency;
+};
+
+static enum supplicant_state string2state(const char *state)
+{
+ if (state == NULL)
+ return SUPPLICANT_STATE_UNKNOWN;
+
+ if (g_str_equal(state, "unknown") == TRUE)
+ return SUPPLICANT_STATE_UNKNOWN;
+ else if (g_str_equal(state, "disconnected") == TRUE)
+ return SUPPLICANT_STATE_DISCONNECTED;
+ else if (g_str_equal(state, "inactive") == TRUE)
+ return SUPPLICANT_STATE_INACTIVE;
+ else if (g_str_equal(state, "scanning") == TRUE)
+ return SUPPLICANT_STATE_SCANNING;
+ else if (g_str_equal(state, "authenticating") == TRUE)
+ return SUPPLICANT_STATE_AUTHENTICATING;
+ else if (g_str_equal(state, "associating") == TRUE)
+ return SUPPLICANT_STATE_ASSOCIATING;
+ else if (g_str_equal(state, "associated") == TRUE)
+ return SUPPLICANT_STATE_ASSOCIATED;
+ else if (g_str_equal(state, "group_handshake") == TRUE)
+ return SUPPLICANT_STATE_GROUP_HANDSHAKE;
+ else if (g_str_equal(state, "4way_handshake") == TRUE)
+ return SUPPLICANT_STATE_4WAY_HANDSHAKE;
+ else if (g_str_equal(state, "completed") == TRUE)
+ return SUPPLICANT_STATE_COMPLETED;
+
+ return SUPPLICANT_STATE_UNKNOWN;
+}
- switch (dbus_message_iter_get_arg_type(iter)) {
- case DBUS_TYPE_STRING:
- case DBUS_TYPE_OBJECT_PATH:
- dbus_message_iter_get_basic(iter, &str);
- DBG("%s = %s", key, str);
- break;
- case DBUS_TYPE_BYTE:
- case DBUS_TYPE_BOOLEAN:
- dbus_message_iter_get_basic(iter, &byte);
- DBG("%s = %u", key, byte);
- break;
- case DBUS_TYPE_ARRAY:
- DBG("%s = {array}", key);
- dbus_message_iter_recurse(iter, &array);
- while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) {
- dbus_message_iter_get_basic(&array, &str);
- DBG(" %s", str);
- dbus_message_iter_next(&array);
+static void callback_interface_added(struct supplicant_interface *interface)
+{
+ if (callbacks_pointer == NULL)
+ return;
+
+ if (callbacks_pointer->interface_added == NULL)
+ return;
+
+ callbacks_pointer->interface_added(interface);
+}
+
+static void callback_interface_removed(struct supplicant_interface *interface)
+{
+ if (callbacks_pointer == NULL)
+ return;
+
+ if (callbacks_pointer->interface_removed == NULL)
+ return;
+
+ callbacks_pointer->interface_removed(interface);
+}
+
+static void callback_network_added(struct supplicant_network *network)
+{
+ if (callbacks_pointer == NULL)
+ return;
+
+ if (callbacks_pointer->network_added == NULL)
+ return;
+
+ callbacks_pointer->network_added(network);
+}
+
+static void callback_network_removed(struct supplicant_network *network)
+{
+ if (callbacks_pointer == NULL)
+ return;
+
+ if (callbacks_pointer->network_removed == NULL)
+ return;
+
+ callbacks_pointer->network_removed(network);
+}
+
+static void remove_interface(gpointer data)
+{
+ struct supplicant_interface *interface = data;
+
+ callback_interface_removed(interface);
+
+ g_hash_table_destroy(interface->bss_mapping);
+ g_hash_table_destroy(interface->network_table);
+
+ g_free(interface->path);
+ g_free(interface->ifname);
+ g_free(interface->driver);
+ g_free(interface->bridge);
+ g_free(interface);
+}
+
+static void remove_network(gpointer data)
+{
+ struct supplicant_network *network = data;
+
+ callback_network_removed(network);
+
+ g_free(network->group);
+ g_free(network->name);
+ g_free(network);
+}
+
+static void remove_bss(gpointer data)
+{
+ struct supplicant_bss *bss = data;
+
+ g_free(bss->path);
+ g_free(bss);
+}
+
+static void debug_eap_methods(void)
+{
+ int i;
+
+ for (i = 0; eap_method_map[i].str != NULL; i++) {
+ if (eap_methods & eap_method_map[i].val)
+ DBG("EAP Method: %s", eap_method_map[i].str);
+ }
+}
+
+static void debug_scan_capabilities(struct supplicant_interface *interface)
+{
+ int i;
+
+ for (i = 0; scan_capa_map[i].str != NULL; i++) {
+ if (interface->scan_capa & scan_capa_map[i].val)
+ DBG("Scan Capability: %s", scan_capa_map[i].str);
+ }
+}
+
+static void interface_capability_scan(DBusMessageIter *iter, void *user_data)
+{
+ struct supplicant_interface *interface = user_data;
+ const char *str = NULL;
+ int i;
+
+ dbus_message_iter_get_basic(iter, &str);
+ if (str == NULL)
+ return;
+
+ for (i = 0; scan_capa_map[i].str != NULL; i++)
+ if (strcmp(str, scan_capa_map[i].str) == 0) {
+ interface->scan_capa |= scan_capa_map[i].val;
+ break;
}
- break;
- default:
- DBG("%s = ...", key);
- break;
+}
+
+static void interface_capability(const char *key, DBusMessageIter *iter,
+ void *user_data)
+{
+ struct supplicant_interface *interface = user_data;
+
+ if (key == NULL)
+ return;
+
+ if (g_strcmp0(key, "Scan") == 0)
+ supplicant_dbus_array_foreach(iter, interface_capability_scan,
+ interface);
+ else
+ DBG("key %s type %c",
+ key, dbus_message_iter_get_arg_type(iter));
+}
+
+const char *supplicant_interface_get_ifname(struct supplicant_interface *interface)
+{
+ if (interface == NULL)
+ return NULL;
+
+ return interface->ifname;
+}
+
+struct supplicant_interface *supplicant_network_get_interface(struct supplicant_network *network)
+{
+ if (network == NULL)
+ return NULL;
+
+ return network->interface;
+}
+
+const char *supplicant_network_get_name(struct supplicant_network *network)
+{
+ if (network == NULL || network->name == NULL)
+ return "";
+
+ return network->name;
+}
+
+enum supplicant_network_mode supplicant_network_get_mode(struct supplicant_network *network)
+{
+ if (network == NULL)
+ return SUPPLICANT_NETWORK_MODE_UNKNOWN;
+
+ return network->mode;
+}
+
+static void network_property(const char *key, DBusMessageIter *iter,
+ void *user_data)
+{
+ if (key == NULL)
+ return;
+
+ DBG("key %s type %c", key, dbus_message_iter_get_arg_type(iter));
+}
+
+static void interface_network_added(DBusMessageIter *iter, void *user_data)
+{
+ const char *path = NULL;
+
+ dbus_message_iter_get_basic(iter, &path);
+ if (path == NULL)
+ return;
+
+ supplicant_dbus_property_get_all(path,
+ SUPPLICANT_INTERFACE ".Interface.Network",
+ network_property, NULL);
+}
+
+static char *create_name(unsigned char *ssid, int ssid_len)
+{
+ char *name;
+ int i;
+
+ if (ssid_len < 1 || ssid[0] == '\0')
+ name = NULL;
+ else
+ name = g_try_malloc0(ssid_len + 1);
+
+ if (name == NULL)
+ return g_strdup("");
+
+ for (i = 0; i < ssid_len; i++) {
+ if (g_ascii_isprint(ssid[i]))
+ name[i] = ssid[i];
+ else
+ name[i] = ' ';
}
+
+ return name;
}
-static void properties_decode(DBusMessageIter *iter)
+static void add_bss_to_network(struct supplicant_bss *bss)
{
- DBusMessageIter dict;
+ struct supplicant_interface *interface = bss->interface;
+ struct supplicant_network *network;
+ GString *str;
+ char *group;
+ unsigned int i;
+
+ str = g_string_sized_new((bss->ssid_len * 2) + 24);
+ if (str == NULL)
+ return;
+
+ if (bss->ssid_len > 0 && bss->ssid[0] != '\0') {
+ for (i = 0; i < bss->ssid_len; i++)
+ g_string_append_printf(str, "%02x", bss->ssid[i]);
+ } else
+ g_string_append_printf(str, "hidden");
- if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
- syslog(LOG_ERR, "Invalid message type");
+ group = g_string_free(str, FALSE);
+
+ network = g_hash_table_lookup(interface->network_table, group);
+ if (network != NULL) {
+ g_free(group);
+ goto done;
+ }
+
+ network = g_try_new0(struct supplicant_network, 1);
+ if (network == NULL) {
+ g_free(group);
return;
}
- dbus_message_iter_recurse(iter, &dict);
+ network->group = group;
+ network->name = create_name(bss->ssid, bss->ssid_len);
- while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
- DBusMessageIter entry, value;
- const char *key;
+ network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, remove_bss);
- dbus_message_iter_recurse(&dict, &entry);
+ g_hash_table_replace(interface->network_table,
+ network->group, network);
- if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
- return;
+ callback_network_added(network);
- dbus_message_iter_get_basic(&entry, &key);
- dbus_message_iter_next(&entry);
+done:
+ g_hash_table_replace(interface->bss_mapping, bss->path, network);
+ g_hash_table_replace(network->bss_table, bss->path, bss);
+}
- if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
- return;
+static void bss_property(const char *key, DBusMessageIter *iter,
+ void *user_data)
+{
+ struct supplicant_bss *bss = user_data;
+
+ if (bss->interface == NULL)
+ return;
+
+ if (key == NULL) {
+ add_bss_to_network(bss);
+ return;
+ }
+
+ if (g_strcmp0(key, "BSSID") == 0) {
+ DBusMessageIter array;
+ unsigned char *addr;
+ int addr_len;
+
+ dbus_message_iter_recurse(iter, &array);
+ dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
+
+ if (addr_len == 6)
+ memcpy(bss->bssid, addr, addr_len);
+ } else if (g_strcmp0(key, "SSID") == 0) {
+ DBusMessageIter array;
+ unsigned char *ssid;
+ int ssid_len;
+
+ dbus_message_iter_recurse(iter, &array);
+ dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
+
+ if (ssid_len > 0 && ssid_len < 33) {
+ memcpy(bss->ssid, ssid, ssid_len);
+ bss->ssid_len = ssid_len;
+ } else {
+ memset(bss->ssid, 0, sizeof(bss->ssid));
+ bss->ssid_len = 0;
+ }
+ } else if (g_strcmp0(key, "Capabilities") == 0) {
+ unsigned char capabilities = 0x00;
+
+ dbus_message_iter_get_basic(iter, &capabilities);
+ } else if (g_strcmp0(key, "Frequency") == 0) {
+ dbus_int32_t frequency = 0;
+
+ dbus_message_iter_get_basic(iter, &frequency);
+ bss->frequency = frequency;
+ } else if (g_strcmp0(key, "Level") == 0) {
+ dbus_int32_t level = 0;
+
+ dbus_message_iter_get_basic(iter, &level);
+ } else if (g_strcmp0(key, "MaxRate") == 0) {
+ dbus_int32_t maxrate = 0;
+
+ dbus_message_iter_get_basic(iter, &maxrate);
+ } else if (g_strcmp0(key, "RSNIE") == 0) {
+ DBusMessageIter array;
+ unsigned char *ie;
+ int ie_len;
+
+ dbus_message_iter_recurse(iter, &array);
+ dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
+ } else if (g_strcmp0(key, "WPAIE") == 0) {
+ DBusMessageIter array;
+ unsigned char *ie;
+ int ie_len;
+
+ dbus_message_iter_recurse(iter, &array);
+ dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
+ } else if (g_strcmp0(key, "WPSIE") == 0) {
+ DBusMessageIter array;
+ unsigned char *ie;
+ int ie_len;
- dbus_message_iter_recurse(&entry, &value);
+ dbus_message_iter_recurse(iter, &array);
+ dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
+ } else
+ DBG("key %s type %c",
+ key, dbus_message_iter_get_arg_type(iter));
+}
- show_property(key, &value);
+static void interface_bss_added(DBusMessageIter *iter, void *user_data)
+{
+ struct supplicant_interface *interface = user_data;
+ struct supplicant_network *network;
+ struct supplicant_bss *bss;
+ const char *path = NULL;
- dbus_message_iter_next(&dict);
+ dbus_message_iter_get_basic(iter, &path);
+ if (path == NULL)
+ return;
+
+ network = g_hash_table_lookup(interface->bss_mapping, path);
+ if (network != NULL) {
+ bss = g_hash_table_lookup(network->bss_table, path);
+ if (bss != NULL)
+ return;
}
+
+ bss = g_try_new0(struct supplicant_bss, 1);
+ if (bss == NULL)
+ return;
+
+ bss->interface = interface;
+ bss->path = g_strdup(path);
+
+ supplicant_dbus_property_get_all(path,
+ SUPPLICANT_INTERFACE ".Interface.BSS",
+ bss_property, bss);
}
-static void properties_get_all_reply(DBusPendingCall *call, void *user_data)
+static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
{
- DBusMessage *reply;
- DBusMessageIter iter;
+ struct supplicant_interface *interface = user_data;
+ struct supplicant_network *network;
+ const char *path = NULL;
- DBG("call %p", call);
+ dbus_message_iter_get_basic(iter, &path);
+ if (path == NULL)
+ return;
- reply = dbus_pending_call_steal_reply(call);
- if (reply == NULL)
+ network = g_hash_table_lookup(interface->bss_mapping, path);
+ if (network == NULL)
return;
- if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
- goto failed;
+ g_hash_table_remove(interface->bss_mapping, path);
+ g_hash_table_remove(network->bss_table, path);
- if (dbus_message_iter_init(reply, &iter) == FALSE)
- goto failed;
+ if (g_hash_table_size(network->bss_table) == 0)
+ g_hash_table_remove(interface->network_table, network->group);
+}
- DBG("success");
+static void interface_property(const char *key, DBusMessageIter *iter,
+ void *user_data)
+{
+ struct supplicant_interface *interface = user_data;
- properties_decode(&iter);
+ if (interface == NULL)
+ return;
+
+ if (key == NULL) {
+ debug_scan_capabilities(interface);
+
+ g_hash_table_replace(interface_table,
+ interface->path, interface);
+
+ callback_interface_added(interface);
+ return;
+ }
- dbus_message_unref(reply);
+ if (g_strcmp0(key, "Capabilities") == 0) {
+ supplicant_dbus_property_foreach(iter, interface_capability,
+ interface);
+ } else if (g_strcmp0(key, "State") == 0) {
+ const char *str = NULL;
+
+ dbus_message_iter_get_basic(iter, &str);
+ if (str != NULL)
+ interface->state = string2state(str);
+ } else if (g_strcmp0(key, "Scanning") == 0) {
+ dbus_bool_t scanning = FALSE;
+
+ dbus_message_iter_get_basic(iter, &scanning);
+ interface->scanning = scanning;
+ } else if (g_strcmp0(key, "ApScan") == 0) {
+ int apscan;
+
+ dbus_message_iter_get_basic(iter, &apscan);
+ interface->apscan = apscan;
+ } else if (g_strcmp0(key, "Ifname") == 0) {
+ const char *str = NULL;
+
+ dbus_message_iter_get_basic(iter, &str);
+ if (str != NULL)
+ interface->ifname = g_strdup(str);
+ } else if (g_strcmp0(key, "Driver") == 0) {
+ const char *str = NULL;
- return;
+ dbus_message_iter_get_basic(iter, &str);
+ if (str != NULL)
+ interface->driver = g_strdup(str);
+ } else if (g_strcmp0(key, "BridgeIfname") == 0) {
+ const char *str = NULL;
-failed:
- dbus_message_unref(reply);
+ dbus_message_iter_get_basic(iter, &str);
+ if (str != NULL)
+ interface->bridge = g_strdup(str);
+ } else if (g_strcmp0(key, "CurrentBSS") == 0) {
+ interface_bss_added(iter, interface);
+ } else if (g_strcmp0(key, "CurrentNetwork") == 0) {
+ interface_network_added(iter, interface);
+ } else if (g_strcmp0(key, "BSSs") == 0) {
+ supplicant_dbus_array_foreach(iter, interface_bss_added,
+ interface);
+ } else if (g_strcmp0(key, "Blobs") == 0) {
+ } else if (g_strcmp0(key, "Networks") == 0) {
+ supplicant_dbus_array_foreach(iter, interface_network_added,
+ interface);
+ } else
+ DBG("key %s type %c",
+ key, dbus_message_iter_get_arg_type(iter));
}
-static int properties_get_all(const char *path, const char *interface)
+static void interface_path(DBusMessageIter *iter, void *user_data)
{
- DBusMessage *message;
- DBusPendingCall *call;
+ struct supplicant_interface *interface;
+ const char *path = NULL;
- DBG("");
+ dbus_message_iter_get_basic(iter, &path);
+ if (path == NULL)
+ return;
- message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
- DBUS_INTERFACE_PROPERTIES, "GetAll");
- if (message == NULL)
- return -ENOMEM;
+ interface = g_hash_table_lookup(interface_table, path);
+ if (interface != NULL)
+ return;
- dbus_message_set_auto_start(message, FALSE);
+ interface = g_try_new0(struct supplicant_interface, 1);
+ if (interface == NULL)
+ return;
- dbus_message_append_args(message, DBUS_TYPE_STRING, &interface, NULL);
+ interface->path = g_strdup(path);
- if (dbus_connection_send_with_reply(connection, message,
- &call, TIMEOUT) == FALSE) {
- syslog(LOG_ERR, "Failed to add interface");
- dbus_message_unref(message);
- return -EIO;
- }
+ interface->network_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, remove_network);
- if (call == NULL) {
- syslog(LOG_ERR, "D-Bus connection not available");
- dbus_message_unref(message);
- return -EIO;
+ interface->bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, NULL);
+
+ supplicant_dbus_property_get_all(path,
+ SUPPLICANT_INTERFACE ".Interface",
+ interface_property, interface);
+}
+
+static void eap_method(DBusMessageIter *iter, void *user_data)
+{
+ const char *str = NULL;
+ int i;
+
+ dbus_message_iter_get_basic(iter, &str);
+ if (str == NULL)
+ return;
+
+ for (i = 0; eap_method_map[i].str != NULL; i++)
+ if (strcmp(str, eap_method_map[i].str) == 0) {
+ eap_methods |= eap_method_map[i].val;
+ break;
+ }
+}
+
+static void service_property(const char *key, DBusMessageIter *iter,
+ void *user_data)
+{
+ if (key == NULL)
+ return;
+
+ if (g_strcmp0(key, "Interfaces") == 0)
+ supplicant_dbus_array_foreach(iter, interface_path, user_data);
+ else if (g_strcmp0(key, "EapMethods") == 0) {
+ supplicant_dbus_array_foreach(iter, eap_method, user_data);
+ debug_eap_methods();
+ } else if (g_strcmp0(key, "DebugParams") == 0) {
}
+}
- DBG("call %p", call);
+static void signal_interface_added(const char *path, DBusMessageIter *iter)
+{
+ interface_path(iter, NULL);
+}
- dbus_pending_call_set_notify(call, properties_get_all_reply,
- NULL, NULL);
+static void signal_interface_removed(const char *path, DBusMessageIter *iter)
+{
+ DBG("path %s", path);
+}
- dbus_message_unref(message);
+static void signal_bss_added(const char *path, DBusMessageIter *iter)
+{
+ struct supplicant_interface *interface;
- return 0;
+ interface = g_hash_table_lookup(interface_table, path);
+ if (interface == NULL)
+ return;
+
+ interface_bss_added(iter, interface);
}
-static DBusHandlerResult supplicant_filter(DBusConnection *conn,
- DBusMessage *msg, void *data)
+static void signal_bss_removed(const char *path, DBusMessageIter *iter)
{
- int prefixlen = strlen(SUPPLICANT_INTERFACE);
- const char *interface, *member, *path;
+ struct supplicant_interface *interface;
- interface = dbus_message_get_interface(msg);
+ interface = g_hash_table_lookup(interface_table, path);
if (interface == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ return;
- if (g_str_has_prefix(interface, SUPPLICANT_INTERFACE) == FALSE)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ interface_bss_removed(iter, interface);
+}
+
+static struct {
+ const char *interface;
+ const char *member;
+ void (*function) (const char *path, DBusMessageIter *iter);
+} signal_map[] = {
+ { SUPPLICANT_INTERFACE, "InterfaceAdded", signal_interface_added },
+ { SUPPLICANT_INTERFACE, "InterfaceRemoved", signal_interface_removed },
+ { SUPPLICANT_INTERFACE ".Interface", "BSSAdded", signal_bss_added },
+ { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved", signal_bss_removed },
+ { }
+};
- member = dbus_message_get_member(msg);
- if (member == NULL)
+static DBusHandlerResult supplicant_filter(DBusConnection *conn,
+ DBusMessage *message, void *data)
+{
+ DBusMessageIter iter;
+ const char *path;
+ int i;
+
+ path = dbus_message_get_path(message);
+ if (path == NULL)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- path = dbus_message_get_path(msg);
+ if (dbus_message_iter_init(message, &iter) == FALSE)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- syslog(LOG_DEBUG, "[ %s ]%s.%s", path, interface + prefixlen, member);
+ for (i = 0; signal_map[i].interface != NULL; i++) {
+ if (dbus_message_has_interface(message,
+ signal_map[i].interface) == FALSE)
+ continue;
- if (g_str_equal(member, "PropertiesChanged") == TRUE) {
- DBusMessageIter iter;
+ if (dbus_message_has_member(message,
+ signal_map[i].member) == FALSE)
+ continue;
- if (dbus_message_iter_init(msg, &iter) == TRUE)
- properties_decode(&iter);
+ signal_map[i].function(path, &iter);
+ break;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -226,8 +741,6 @@ static const char *supplicant_rule6 = "type=signal,"
int supplicant_register(const struct supplicant_callbacks *callbacks)
{
- DBG("");
-
connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
if (connection == NULL)
return -EIO;
@@ -240,6 +753,12 @@ int supplicant_register(const struct supplicant_callbacks *callbacks)
}
callbacks_pointer = callbacks;
+ eap_methods = 0;
+
+ interface_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, remove_interface);
+
+ supplicant_dbus_setup(connection);
dbus_bus_add_match(connection, supplicant_rule1, NULL);
dbus_bus_add_match(connection, supplicant_rule2, NULL);
@@ -249,15 +768,15 @@ int supplicant_register(const struct supplicant_callbacks *callbacks)
dbus_bus_add_match(connection, supplicant_rule6, NULL);
dbus_connection_flush(connection);
- properties_get_all(SUPPLICANT_PATH, SUPPLICANT_INTERFACE);
+ supplicant_dbus_property_get_all(SUPPLICANT_PATH,
+ SUPPLICANT_INTERFACE,
+ service_property, NULL);
return 0;
}
void supplicant_unregister(const struct supplicant_callbacks *callbacks)
{
- DBG("");
-
if (connection != NULL) {
dbus_bus_remove_match(connection, supplicant_rule6, NULL);
dbus_bus_remove_match(connection, supplicant_rule5, NULL);
@@ -269,10 +788,18 @@ void supplicant_unregister(const struct supplicant_callbacks *callbacks)
dbus_connection_remove_filter(connection,
supplicant_filter, NULL);
+ }
+ if (interface_table != NULL) {
+ g_hash_table_destroy(interface_table);
+ interface_table = NULL;
+ }
+
+ if (connection != NULL) {
dbus_connection_unref(connection);
connection = NULL;
}
callbacks_pointer = NULL;
+ eap_methods = 0;
}