#include #include #include #include #include #include #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, };