diff options
Diffstat (limited to 'src/plugins/wireless/plugin.c')
-rw-r--r-- | src/plugins/wireless/plugin.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/plugins/wireless/plugin.c b/src/plugins/wireless/plugin.c new file mode 100644 index 0000000..1ddeb95 --- /dev/null +++ b/src/plugins/wireless/plugin.c @@ -0,0 +1,148 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <dirent.h> + +#include "wpa_ctrl.h" +#include "plugin.h" + +#define WIRELESS_PATH PLUGIN_ROOT_PATH "/wireless" +#define WIRELESS_INTERFACE PLUGIN_ROOT_INTF ".wireless" + +static int init(plugin_t *plugin, DBusConnection *connection); +static void deinit(plugin_t *plugin, DBusConnection *connection); +static void handle_incoming(plugin_t *plugin, DBusConnection *connection); +static DBusHandlerResult handle_message(DBusConnection *connection, DBusMessage *message, plugin_t *plugin); +static DBusHandlerResult select_network(DBusConnection *connection, DBusMessage *message, plugin_t *plugin); +static DBusHandlerResult wpa_supplicant_request(DBusConnection *connection, DBusMessage *message, plugin_t *plugin, char *cmd); + +static int init(plugin_t *plugin, DBusConnection *connection) { + struct wpa_ctrl *ctrl_conn = NULL; + const char *ctrl_iface_dir = "/var/run/wpa_supplicant"; + DIR *dir = opendir(ctrl_iface_dir); + + if (dir) { + struct dirent *dent; + while ((dent = readdir(dir))) { + char *cfile; + int flen; + if (strcmp(dent->d_name, ".") == 0 || + strcmp(dent->d_name, "..") == 0) + continue; + printf("Selected interface '%s'\n", + dent->d_name); + flen = strlen(ctrl_iface_dir) + strlen(dent->d_name) + 2; + cfile = malloc(flen); + if (cfile == NULL) + return -1; + snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, dent->d_name); + ctrl_conn = wpa_ctrl_open(cfile); + free(cfile); + break; + } + closedir(dir); + } + + if (ctrl_conn != NULL) { + plugin->fd = wpa_ctrl_get_fd(ctrl_conn); + } else { + /* do not fail, the plugin will try to re-init when needed */ + plugin->fd = -1; + } + plugin->priv = (void *) ctrl_conn; + return 0; +} + +static void deinit(plugin_t *plugin, DBusConnection *connection) { + if (plugin->fd > 0) + close(plugin->fd); +} + +static void handle_incoming(plugin_t *plugin, DBusConnection *connection) { + struct wpa_ctrl *ctrl_conn = (struct wpa_ctrl *) plugin->priv; + char buf[2048]; + size_t len; + wpa_ctrl_recv(ctrl_conn, buf, &len); + buf[len] = '\0'; + printf("received event: %s\n", buf); +} + +static DBusHandlerResult handle_message(DBusConnection *connection, DBusMessage *message, plugin_t *plugin) { + if (dbus_message_is_method_call(message, WIRELESS_INTERFACE, "ScanResults")) { + return wpa_supplicant_request(connection, message, plugin, "SCAN_RESULTS"); + } else if (dbus_message_is_method_call(message, WIRELESS_INTERFACE, "ListNetworks")) { + return wpa_supplicant_request(connection, message, plugin, "LIST_NETWORKS"); + } else if (dbus_message_is_method_call(message, WIRELESS_INTERFACE, "SelectNetwork")) { + return select_network(connection, message, plugin); + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult select_network(DBusConnection *connection, DBusMessage *message, plugin_t *plugin) { + DBusError error; + u_int32_t net; + char cmd[32]; + + dbus_error_init (&error); + if (!dbus_message_get_args (message, + &error, + DBUS_TYPE_UINT32, + &net, + DBUS_TYPE_INVALID)) { + fprintf(stderr, "select_network(): failed to read D-BUS message args: %s\n", error.message); + dbus_error_free (&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + dbus_error_free (&error); + + snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %u", net); + return wpa_supplicant_request(connection, message, plugin, cmd); +} + +static DBusHandlerResult wpa_supplicant_request(DBusConnection *connection, DBusMessage *message, plugin_t *plugin, char *cmd) { + struct wpa_ctrl *ctrl_conn = (struct wpa_ctrl *) plugin->priv; + DBusMessage *reply; + char buf[2048]; + size_t len; + int ret = -1; + + len = sizeof(buf) - 1; + if (ctrl_conn) { + ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, &len, NULL); + } + if (ret == -1) { + fprintf(stderr, "connection to wpa_supplicant daemon lost, reconnecting\n"); + init(plugin, connection); + ctrl_conn = (struct wpa_ctrl *) plugin->priv; + if (ctrl_conn) { + ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, &len, NULL); + } + } + if (ret != 0) { + fprintf(stderr, "unable to request command\n"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + buf[len] = '\0'; + + reply = dbus_message_new_method_return(message); + dbus_message_append_args(reply, + DBUS_TYPE_STRING, + buf, + DBUS_TYPE_INVALID); + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +plugin_t wpa_supplicant_plugin = { + .name = "Wireless", + .path = WIRELESS_PATH, + .init = init, + .handle_incoming = handle_incoming, + .handle_message = handle_message, + .deinit = deinit, +}; |