/** * wpas_dbus_global_get_interface - Get the object path for an interface name * @message: Pointer to incoming dbus message * @global: %wpa_supplicant global data structure * Returns: The object path of the interface object, * or a dbus error message with more information * * Handler function for "getInterface" method call. Handles requests * by dbus clients for the object path of an specific network interface. */ DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message, struct wpa_global *global) { DBusMessage *reply = NULL; const char *ifname; const char *path; struct wpa_supplicant *wpa_s; if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname, DBUS_TYPE_INVALID)) { reply = wpas_dbus_new_invalid_opts_error(message, NULL); goto out; } wpa_s = wpa_supplicant_get_iface(global, ifname); if (wpa_s == NULL) { reply = wpas_dbus_new_invalid_iface_error(message); goto out; } path = wpa_s->dbus_path; reply = dbus_message_new_method_return(message); dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); out: return reply; }
/** * wpas_dbus_iface_select_network - Attempt association with a configured network * @message: Pointer to incoming dbus message * @wpa_s: wpa_supplicant structure for a network interface * Returns: A dbus message containing a UINT32 indicating success (1) or * failure (0) * * Handler function for "selectNetwork" method call of network interface. */ DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message, struct wpa_supplicant *wpa_s) { DBusMessage *reply = NULL; const char *op; struct wpa_ssid *ssid; char *iface_obj_path = NULL; char *network = NULL; if (os_strlen(dbus_message_get_signature(message)) == 0) { /* Any network */ ssid = NULL; } else { int nid; if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, DBUS_TYPE_INVALID)) { reply = wpas_dbus_new_invalid_opts_error(message, NULL); goto out; } /* Extract the network number */ iface_obj_path = wpas_dbus_decompose_object_path(op, &network, NULL); if (iface_obj_path == NULL) { reply = wpas_dbus_new_invalid_iface_error(message); goto out; } /* Ensure the object path really points to this interface */ if (os_strcmp(iface_obj_path, wpa_s->dbus_path) != 0) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } nid = strtoul(network, NULL, 10); if (errno == EINVAL) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } ssid = wpa_config_get_network(wpa_s->conf, nid); if (ssid == NULL) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } } /* Finally, associate with the network */ wpa_supplicant_select_network(wpa_s, ssid); reply = wpas_dbus_new_success_reply(message); out: os_free(iface_obj_path); os_free(network); return reply; }
/** * wpas_dbus_global_remove_interface - Request deregistration of an interface * @message: Pointer to incoming dbus message * @global: wpa_supplicant global data structure * Returns: a dbus message containing a UINT32 indicating success (1) or * failure (0), or returns a dbus error message with more information * * Handler function for "removeInterface" method call. Handles requests * by dbus clients to deregister a network interface that wpa_supplicant * currently manages. */ DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message, struct wpa_global *global) { struct wpa_supplicant *wpa_s; char *path; DBusMessage *reply = NULL; if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) { reply = wpas_dbus_new_invalid_opts_error(message, NULL); goto out; } wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path); if (wpa_s == NULL) { reply = wpas_dbus_new_invalid_iface_error(message); goto out; } if (!wpa_supplicant_remove_iface(global, wpa_s, 0)) { reply = wpas_dbus_new_success_reply(message); } else { reply = dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR, "wpa_supplicant couldn't " "remove this interface."); } out: return reply; }
/** * wpas_iface_message_handler - Dispatch messages for interfaces or networks * @connection: Connection to the system message bus * @message: An incoming dbus message * @user_data: A pointer to a dbus control interface data structure * Returns: Whether or not the message was handled * * This function dispatches all incoming dbus messages for network interfaces, * or objects owned by them, such as scanned BSSIDs and configured networks. */ static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection, DBusMessage *message, void *user_data) { struct wpa_supplicant *wpa_s = user_data; const char *method = dbus_message_get_member(message); const char *path = dbus_message_get_path(message); const char *msg_interface = dbus_message_get_interface(message); char *iface_obj_path = NULL; char *network = NULL; char *bssid = NULL; DBusMessage *reply = NULL; /* Caller must specify a message interface */ if (!msg_interface) goto out; iface_obj_path = wpas_dbus_decompose_object_path(path, &network, &bssid); if (iface_obj_path == NULL) { reply = wpas_dbus_new_invalid_iface_error(message); goto out; } /* Make sure the message's object path actually refers to the * wpa_supplicant structure it's supposed to (which is wpa_s) */ if (wpa_supplicant_get_iface_by_dbus_path(wpa_s->global, iface_obj_path) != wpa_s) { reply = wpas_dbus_new_invalid_iface_error(message); goto out; } if (network && !strcmp(msg_interface, WPAS_DBUS_IFACE_NETWORK)) { /* A method for one of this interface's configured networks */ int nid = strtoul(network, NULL, 10); if (errno != EINVAL) reply = wpas_dispatch_network_method(message, wpa_s, nid); else reply = wpas_dbus_new_invalid_network_error(message); } else if (bssid && !strcmp(msg_interface, WPAS_DBUS_IFACE_BSSID)) { /* A method for one of this interface's scanned BSSIDs */ reply = wpas_dispatch_bssid_method(message, wpa_s, bssid); } else if (!strcmp(msg_interface, WPAS_DBUS_IFACE_INTERFACE)) { /* A method for an interface only. */ if (!strcmp(method, "scan")) reply = wpas_dbus_iface_scan(message, wpa_s); else if (!strcmp(method, "scanResults")) reply = wpas_dbus_iface_scan_results(message, wpa_s); else if (!strcmp(method, "addNetwork")) reply = wpas_dbus_iface_add_network(message, wpa_s); else if (!strcmp(method, "removeNetwork")) reply = wpas_dbus_iface_remove_network(message, wpa_s); else if (!strcmp(method, "selectNetwork")) reply = wpas_dbus_iface_select_network(message, wpa_s); else if (!strcmp(method, "capabilities")) reply = wpas_dbus_iface_capabilities(message, wpa_s); else if (!strcmp(method, "disconnect")) reply = wpas_dbus_iface_disconnect(message, wpa_s); else if (!strcmp(method, "setAPScan")) reply = wpas_dbus_iface_set_ap_scan(message, wpa_s); else if (!strcmp(method, "setSmartcardModules")) reply = wpas_dbus_iface_set_smartcard_modules(message, wpa_s); else if (!strcmp(method, "state")) reply = wpas_dbus_iface_get_state(message, wpa_s); else if (!strcmp(method, "scanning")) reply = wpas_dbus_iface_get_scanning(message, wpa_s); else if (!strcmp(method, "setBlobs")) reply = wpas_dbus_iface_set_blobs(message, wpa_s); else if (!strcmp(method, "removeBlobs")) reply = wpas_dbus_iface_remove_blobs(message, wpa_s); #ifdef CONFIG_WPS else if (!os_strcmp(method, "wpsPbc")) reply = wpas_dbus_iface_wps_pbc(message, wpa_s); else if (!os_strcmp(method, "wpsPin")) reply = wpas_dbus_iface_wps_pin(message, wpa_s); else if (!os_strcmp(method, "wpsReg")) reply = wpas_dbus_iface_wps_reg(message, wpa_s); #endif /* CONFIG_WPS */ else if (!os_strcmp(method, "flush")) reply = wpas_dbus_iface_flush(message, wpa_s); } /* If the message was handled, send back the reply */ if (reply) { if (!dbus_message_get_no_reply(message)) dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); } out: os_free(iface_obj_path); os_free(network); os_free(bssid); return reply ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }
/** * wpas_dbus_iface_select_network - Attempt association with a configured network * @message: Pointer to incoming dbus message * @wpa_s: wpa_supplicant structure for a network interface * Returns: A dbus message containing a UINT32 indicating success (1) or * failure (0) * * Handler function for "selectNetwork" method call of network interface. */ DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message, struct wpa_supplicant *wpa_s) { DBusMessage *reply = NULL; const char *op; struct wpa_ssid *ssid; char *iface_obj_path = NULL; char *network = NULL; if (strlen(dbus_message_get_signature(message)) == 0) { /* Any network */ ssid = wpa_s->conf->ssid; while (ssid) { ssid->disabled = 0; ssid = ssid->next; } wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); } else { const char *obj_path; int nid; if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, DBUS_TYPE_INVALID)) { reply = wpas_dbus_new_invalid_opts_error(message, NULL); goto out; } /* Extract the network number */ iface_obj_path = wpas_dbus_decompose_object_path(op, &network, NULL); if (iface_obj_path == NULL) { reply = wpas_dbus_new_invalid_iface_error(message); goto out; } /* Ensure the object path really points to this interface */ obj_path = wpa_supplicant_get_dbus_path(wpa_s); if (strcmp(iface_obj_path, obj_path) != 0) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } nid = strtoul(network, NULL, 10); if (errno == EINVAL) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } ssid = wpa_config_get_network(wpa_s->conf, nid); if (ssid == NULL) { reply = wpas_dbus_new_invalid_network_error(message); goto out; } /* Finally, associate with the network */ if (ssid != wpa_s->current_ssid && wpa_s->current_ssid) wpa_supplicant_disassociate( wpa_s, WLAN_REASON_DEAUTH_LEAVING); /* Mark all other networks disabled and trigger reassociation */ ssid = wpa_s->conf->ssid; while (ssid) { ssid->disabled = (nid != ssid->id); ssid = ssid->next; } wpa_s->disconnected = 0; wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); } reply = wpas_dbus_new_success_reply(message); out: free(iface_obj_path); free(network); return reply; }