client: add admin submenu and allow command
authorYun-Hao Chung <howardchung@chromium.org>
Wed, 11 Aug 2021 07:08:56 +0000 (15:08 +0800)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 11 Mar 2022 13:38:36 +0000 (19:08 +0530)
This creates a menu - admin and add a commands to bluetoothctl
- allow [clear/uuid1 uuid2 ...]

Reviewed-by: Miao-chen Chou <mcchou@chromium.org>
Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
Makefile.tools
client/admin.c [new file with mode: 0644]
client/admin.h [new file with mode: 0644]
client/main.c

index 8f35410..39f62cb 100755 (executable)
@@ -10,6 +10,8 @@ client_bluetoothctl_SOURCES = client/main.c \
                                        client/adv_monitor.h \
                                        client/adv_monitor.c \
                                        client/gatt.h client/gatt.c \
+                                       client/admin.h \
+                                       client/admin.c \
                                        monitor/uuid.h monitor/uuid.c
 client_bluetoothctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
                                $(GLIB_LIBS) $(DBUS_LIBS) -lreadline
diff --git a/client/admin.c b/client/admin.c
new file mode 100644 (file)
index 0000000..6232e88
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2021 Google LLC
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "gdbus/gdbus.h"
+#include "src/shared/shell.h"
+
+#include "admin.h"
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
+#define _GNU_SOURCE
+#endif
+
+static GDBusProxy *set_proxy;
+static GDBusProxy *status_proxy;
+
+void admin_policy_set_set_proxy(GDBusProxy *proxy)
+{
+       set_proxy = proxy;
+}
+
+void admin_policy_set_status_proxy(GDBusProxy *proxy)
+{
+       status_proxy = proxy;
+}
+
+void admin_policy_read_service_allowlist(DBusConnection *dbus_conn)
+{
+       DBusMessageIter iter, subiter;
+       char *uuid = NULL;
+
+       if (!status_proxy || !g_dbus_proxy_get_property(status_proxy,
+                                               "ServiceAllowList", &iter)) {
+               bt_shell_printf("Failed to get property\n");
+       return bt_shell_noninteractive_quit(EXIT_FAILURE);
+       }
+
+       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+               bt_shell_printf("Unexpected return type\n");
+               return bt_shell_noninteractive_quit(EXIT_FAILURE);
+       }
+
+       bt_shell_printf("Service AllowedList:\n");
+       dbus_message_iter_recurse(&iter, &subiter);
+       while (dbus_message_iter_get_arg_type(&subiter) ==
+                                               DBUS_TYPE_STRING) {
+               dbus_message_iter_get_basic(&subiter, &uuid);
+               bt_shell_printf("\t%s\n", uuid);
+               dbus_message_iter_next(&subiter);
+       }
+
+       return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+struct uuid_list_data {
+       char **uuid_list;
+       size_t num;
+};
+
+static void set_service_setup(DBusMessageIter *iter, void *user_data)
+{
+       struct uuid_list_data *data = user_data;
+       DBusMessageIter arr_iter;
+       size_t i;
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+                                               DBUS_TYPE_STRING_AS_STRING,
+                                               &arr_iter);
+
+       for (i = 0; i < data->num; i++) {
+               dbus_message_iter_append_basic(&arr_iter, DBUS_TYPE_STRING,
+                                                       &data->uuid_list[i]);
+       }
+
+       dbus_message_iter_close_container(iter, &arr_iter);
+}
+
+static void set_service_reply(DBusMessage *message, void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+
+       if (!dbus_set_error_from_message(&error, message)) {
+               bt_shell_printf("Set allowed service successfully\n");
+               return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+       }
+
+       bt_shell_printf("Failed to set service allowed list: %s\n", error.name);
+       dbus_error_free(&error);
+       return bt_shell_noninteractive_quit(EXIT_FAILURE);
+}
+
+void admin_policy_set_service_allowlist(DBusConnection *dbus_connd,
+                                                       int argc, char *argv[])
+{
+       struct uuid_list_data data;
+
+       if (!set_proxy) {
+               bt_shell_printf("Set proxy not ready\n");
+               return bt_shell_noninteractive_quit(EXIT_FAILURE);
+       }
+
+       data.uuid_list = argv;
+       data.num = argc;
+
+       if (!g_dbus_proxy_method_call(set_proxy, "SetServiceAllowList",
+                                       set_service_setup, set_service_reply,
+                                       &data, NULL)) {
+               bt_shell_printf("Failed to call method\n");
+               return bt_shell_noninteractive_quit(EXIT_FAILURE);
+       }
+}
diff --git a/client/admin.h b/client/admin.h
new file mode 100644 (file)
index 0000000..1c8c215
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2021 Google LLC
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ */
+
+void admin_policy_set_set_proxy(GDBusProxy *proxy);
+void admin_policy_set_status_proxy(GDBusProxy *proxy);
+
+void admin_policy_read_service_allowlist(DBusConnection *dbus_conn);
+void admin_policy_set_service_allowlist(DBusConnection *dbus_conn,
+                                                       int argc, char *argv[]);
index 65acccf..32757a4 100644 (file)
@@ -28,6 +28,7 @@
 #include "gatt.h"
 #include "advertising.h"
 #include "adv_monitor.h"
+#include "admin.h"
 
 /* String display constants */
 #define COLORED_NEW    COLOR_GREEN "NEW" COLOR_OFF
@@ -529,6 +530,23 @@ static void admon_manager_added(GDBusProxy *proxy)
        adv_monitor_register_app(dbus_conn);
 }
 
+static void admin_policy_set_added(GDBusProxy *proxy)
+{
+       admin_policy_set_set_proxy(proxy);
+}
+
+static void admin_policy_status_added(GDBusProxy *proxy)
+{
+       struct adapter *adapter;
+
+       adapter = find_ctrl(ctrl_list, g_dbus_proxy_get_path(proxy));
+
+       if (!adapter)
+               return;
+
+       admin_policy_set_status_proxy(proxy);
+}
+
 static void proxy_added(GDBusProxy *proxy, void *user_data)
 {
        const char *interface;
@@ -564,6 +582,10 @@ static void proxy_added(GDBusProxy *proxy, void *user_data)
        } else if (!strcmp(interface,
                                "org.bluez.AdvertisementMonitorManager1")) {
                admon_manager_added(proxy);
+       } else if (!strcmp(interface, "org.bluez.AdminPolicySet1")) {
+               admin_policy_set_added(proxy);
+       } else if (!strcmp(interface, "org.bluez.AdminPolicyStatus1")) {
+               admin_policy_status_added(proxy);
        }
 }
 
@@ -620,6 +642,23 @@ static void adapter_removed(GDBusProxy *proxy)
        }
 }
 
+static void admin_policy_set_removed(GDBusProxy *proxy)
+{
+       admin_policy_set_set_proxy(NULL);
+}
+
+static void admin_policy_status_removed(GDBusProxy *proxy)
+{
+       struct adapter *adapter;
+
+       adapter = find_ctrl(ctrl_list, g_dbus_proxy_get_path(proxy));
+
+       if (!adapter)
+               return;
+
+       admin_policy_set_status_proxy(NULL);
+}
+
 static void proxy_removed(GDBusProxy *proxy, void *user_data)
 {
        const char *interface;
@@ -660,6 +699,10 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
        } else if (!strcmp(interface,
                        "org.bluez.AdvertisementMonitorManager1")) {
                adv_monitor_remove_manager(dbus_conn);
+       } else if (!strcmp(interface, "org.bluez.AdminPolicySet1")) {
+               admin_policy_set_removed(proxy);
+       } else if (!strcmp(interface, "org.bluez.AdminPolicyStatus1")) {
+               admin_policy_status_removed(proxy);
        }
 }
 
@@ -2830,6 +2873,22 @@ static void cmd_adv_monitor_get_supported_info(int argc, char *argv[])
        adv_monitor_get_supported_info();
 }
 
+static void cmd_admin_allow(int argc, char *argv[])
+{
+       if (check_default_ctrl() == FALSE)
+               return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+       if (argc <= 1) {
+               admin_policy_read_service_allowlist(dbus_conn);
+               return;
+       }
+
+       if (strcmp(argv[1], "clear") == 0)
+               argc--;
+
+       admin_policy_set_service_allowlist(dbus_conn, argc - 1, argv + 1);
+}
+
 static const struct bt_shell_menu advertise_menu = {
        .name = "advertise",
        .desc = "Advertise Options Submenu",
@@ -2984,6 +3043,15 @@ static const struct bt_shell_menu gatt_menu = {
        { } },
 };
 
+static const struct bt_shell_menu admin_menu = {
+       .name = "admin",
+       .desc = "Admin Policy Submenu",
+       .entries = {
+       { "allow", "[clear/uuid1 uuid2 ...]", cmd_admin_allow,
+                               "Allow service UUIDs and block rest of them"},
+       {} },
+};
+
 static const struct bt_shell_menu main_menu = {
        .name = "main",
        .entries = {
@@ -3081,6 +3149,7 @@ int main(int argc, char *argv[])
        bt_shell_add_submenu(&advertise_monitor_menu);
        bt_shell_add_submenu(&scan_menu);
        bt_shell_add_submenu(&gatt_menu);
+       bt_shell_add_submenu(&admin_menu);
        bt_shell_set_prompt(PROMPT_OFF);
 
        if (agent_option)