mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-15 00:04:29 +08:00
64abbf7cee
This moves admin submenu to admin.c so it is not mixed up with other submenus code.
221 lines
5.4 KiB
C
221 lines
5.4 KiB
C
/*
|
|
*
|
|
* 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"
|
|
#define _GNU_SOURCE
|
|
|
|
static DBusConnection *dbus_conn;
|
|
static GList *admin_proxies;
|
|
static GDBusProxy *set_proxy;
|
|
static GDBusProxy *status_proxy;
|
|
|
|
static void admin_policy_set_set_proxy(GDBusProxy *proxy)
|
|
{
|
|
set_proxy = proxy;
|
|
}
|
|
|
|
static void admin_policy_set_status_proxy(GDBusProxy *proxy)
|
|
{
|
|
status_proxy = proxy;
|
|
}
|
|
|
|
static 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);
|
|
}
|
|
|
|
static void admin_policy_set_service_allowlist(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);
|
|
}
|
|
}
|
|
|
|
static void cmd_admin_allow(int argc, char *argv[])
|
|
{
|
|
if (argc <= 1) {
|
|
admin_policy_read_service_allowlist(dbus_conn);
|
|
return;
|
|
}
|
|
|
|
if (strcmp(argv[1], "clear") == 0)
|
|
argc--;
|
|
|
|
admin_policy_set_service_allowlist(argc - 1, argv + 1);
|
|
}
|
|
|
|
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 void admin_policy_status_added(GDBusProxy *proxy)
|
|
{
|
|
admin_proxies = g_list_append(admin_proxies, proxy);
|
|
admin_policy_set_status_proxy(proxy);
|
|
}
|
|
|
|
static void proxy_added(GDBusProxy *proxy, void *user_data)
|
|
{
|
|
const char *interface;
|
|
|
|
interface = g_dbus_proxy_get_interface(proxy);
|
|
|
|
if (!strcmp(interface, "org.bluez.AdminPolicySet1"))
|
|
admin_policy_set_set_proxy(proxy);
|
|
else if (!strcmp(interface, "org.bluez.AdminPolicyStatus1"))
|
|
admin_policy_status_added(proxy);
|
|
}
|
|
|
|
static void admin_policy_status_removed(GDBusProxy *proxy)
|
|
{
|
|
admin_proxies = g_list_remove(admin_proxies, proxy);
|
|
admin_policy_set_status_proxy(NULL);
|
|
}
|
|
|
|
static void proxy_removed(GDBusProxy *proxy, void *user_data)
|
|
{
|
|
const char *interface;
|
|
|
|
interface = g_dbus_proxy_get_interface(proxy);
|
|
|
|
if (!strcmp(interface, "org.bluez.AdminPolicySet1"))
|
|
admin_policy_set_set_proxy(NULL);
|
|
else if (!strcmp(interface, "org.bluez.AdminPolicyStatus1"))
|
|
admin_policy_status_removed(proxy);
|
|
}
|
|
|
|
static GDBusClient *client;
|
|
|
|
static void disconnect_handler(DBusConnection *connection, void *user_data)
|
|
{
|
|
g_list_free_full(admin_proxies, NULL);
|
|
admin_proxies = NULL;
|
|
}
|
|
|
|
void admin_add_submenu(void)
|
|
{
|
|
bt_shell_add_submenu(&admin_menu);
|
|
|
|
dbus_conn = bt_shell_get_env("DBUS_CONNECTION");
|
|
if (!dbus_conn || client)
|
|
return;
|
|
|
|
client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
|
|
g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
|
|
NULL, NULL);
|
|
g_dbus_client_set_disconnect_watch(client, disconnect_handler, NULL);
|
|
}
|
|
|
|
void admin_remove_submenu(void)
|
|
{
|
|
g_dbus_client_unref(client);
|
|
client = NULL;
|
|
}
|