From 0ba266d86c903e398bf93ff74de7c071b50c93d5 Mon Sep 17 00:00:00 2001 From: Jintao Lin Date: Mon, 7 Nov 2022 19:25:26 +0000 Subject: [PATCH] dbus: Add virtual interface create/remove logic to be inline with ctrl_iface There is no way to create or remove a virtual interface with wpa_supplicant dbus methods. The platform has to use out-of-band methods to manage the virtual interfaces. This change adds virtual interface create/remove logic to the dbus methods CreateInterface and RemoveInterface to achieve similar functionalities as wpa_cli commands interface_add and interface_remove. Signed-off-by: Jintao Lin --- doc/dbus.doxygen | 2 + wpa_supplicant/dbus/dbus_new_handlers.c | 59 ++++++++++++++++++++++++- wpa_supplicant/wpa_supplicant_i.h | 1 + 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/doc/dbus.doxygen b/doc/dbus.doxygen index f6ab82000..504db7540 100644 --- a/doc/dbus.doxygen +++ b/doc/dbus.doxygen @@ -41,6 +41,8 @@ registered in the bus with fi.w1.wpa_supplicant1 name. BridgeIfnamesName of the bridge interface to control, e.g., br0No DriversDriver name which the interface uses, e.g., nl80211No ConfigFilesConfiguration file pathNo + CreatebWhether to create a new interface in the kernelNo + TypesInterface type to create (sta or ap)No diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 7b9cf2884..e63e2209e 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -704,6 +704,8 @@ DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message, char *ifname = NULL; char *confname = NULL; char *bridge_ifname = NULL; + bool create_iface = false; + enum wpa_driver_if_type if_type = WPA_IF_STATION; dbus_message_iter_init(message, &iter); @@ -740,6 +742,19 @@ DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message, wpa_dbus_dict_entry_clear(&entry); if (bridge_ifname == NULL) goto oom; + } else if (os_strcmp(entry.key, "Create") == 0 && + entry.type == DBUS_TYPE_BOOLEAN) { + create_iface = entry.bool_value; + wpa_dbus_dict_entry_clear(&entry); + } else if (os_strcmp(entry.key, "Type") == 0 && + entry.type == DBUS_TYPE_STRING) { + if (os_strcmp(entry.str_value, "sta") == 0) + if_type = WPA_IF_STATION; + else if (os_strcmp(entry.str_value, "ap") == 0) + if_type = WPA_IF_AP_BSS; + else + goto error; + wpa_dbus_dict_entry_clear(&entry); } else { wpa_dbus_dict_entry_clear(&entry); goto error; @@ -761,6 +776,23 @@ DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message, struct wpa_supplicant *wpa_s; struct wpa_interface iface; + if (create_iface) { + u8 mac_addr[ETH_ALEN]; + + wpa_printf(MSG_DEBUG, + "%s[dbus]: creating an interface '%s'", + __func__, ifname); + if (!global->ifaces || + wpa_drv_if_add(global->ifaces, if_type, ifname, + NULL, NULL, NULL, mac_addr, + NULL) < 0) { + reply = wpas_dbus_error_unknown_error( + message, + "interface creation failed."); + goto out; + } + } + os_memset(&iface, 0, sizeof(iface)); iface.driver = driver; iface.ifname = ifname; @@ -771,6 +803,9 @@ DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message, if (wpa_s && wpa_s->dbus_new_path) { const char *path = wpa_s->dbus_new_path; + wpa_s->added_vif = create_iface; + wpa_s->added_vif_type = create_iface ? if_type : + WPA_IF_MAX; reply = dbus_message_new_method_return(message); dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); @@ -778,6 +813,9 @@ DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message, reply = wpas_dbus_error_unknown_error( message, "wpa_supplicant couldn't grab this interface."); + if (create_iface) + wpa_drv_if_remove(global->ifaces, if_type, + ifname); } } @@ -814,19 +852,36 @@ DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message, struct wpa_supplicant *wpa_s; char *path; DBusMessage *reply = NULL; + bool delete_iface; dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); wpa_s = get_iface_by_dbus_path(global, path); - if (wpa_s == NULL) + if (!wpa_s) { reply = wpas_dbus_error_iface_unknown(message); - else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) { + goto out; + } + delete_iface = wpa_s->added_vif; + if (wpa_supplicant_remove_iface(global, wpa_s, 0)) { reply = wpas_dbus_error_unknown_error( message, "wpa_supplicant couldn't remove this interface."); + goto out; } + if (delete_iface) { + wpa_printf(MSG_DEBUG, "%s[dbus]: deleting the interface '%s'", + __func__, wpa_s->ifname); + if (wpa_drv_if_remove(global->ifaces, wpa_s->added_vif_type, + wpa_s->ifname)) { + reply = wpas_dbus_error_unknown_error( + message, + "wpa_supplicant couldn't delete this interface."); + } + } + +out: return reply; } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index add24f07d..330b80f4d 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -926,6 +926,7 @@ struct wpa_supplicant { unsigned int connection_he:1; unsigned int connection_eht:1; unsigned int disable_mbo_oce:1; + enum wpa_driver_if_type added_vif_type; struct os_reltime last_mac_addr_change; int last_mac_addr_style;