summaryrefslogtreecommitdiffstats
path: root/src/plugins/wireless/plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/wireless/plugin.c')
-rw-r--r--src/plugins/wireless/plugin.c148
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,
+};