2021-07-28 13:17:48

by Yun-hao Chung

[permalink] [raw]
Subject: [Bluez PATCH v3 00/13] Admin policy series

From: Yun-Hao Chung <[email protected]>


Hi manintainers,

This series is to
1. Implement a few methods in core so that a plugin can have control of
allowing / disallowing certain service connections.
2. Implement the AdminPolicy plugin. The plugin provides interfaces
AdminPolicySet and AdminPolicyStatus. For each policy, users should
set the value thorugh AdminPolicySet and query the current setting
through AdminPolicyStatus. We separeted these two interfaces so that
developers can assign different groups of users to these interfaces.
Currently the only policy is ServiceAllowList, which make bluez only
allow a list of service by specified their UUIDs, but the plugin is
also expected to provide more controls over other bluez behaviors.
Since the second part is a plugin, it might not be necessary to land in
upstream tree.

Thanks.

Changes in v3:
- Rename plugins/admin_policy.c -> plugins/admin.c
- Use device_added callback in btd_adapter_driver instead of listen for
dbus
- Add authorization method in profiles/health/mcap.c and block incoming
connections in adapter authorization function.

Changes in v2:
- Move bt_uuid_hash and bt_uuid_equal functions to adapter.c.
- Modify the criteria to say a device is `Affected` from any-of-uuid
to any-of-auto-connect-profile.
- Remove the code to remove/reprobe disallowed/allowed profiles,
instead, check if the service is allowed in bt_io_accept connect_cb.
- Fix a typo in emit_property_change in
plugin/admin_policy.c:set_service_allowlist
- Instead of using device_state_cb, utilize D-BUS client to watch device
added/removed.
- Add a document in doc/

Yun-Hao Chung (13):
core: add is_allowed property in btd_service
core: add adapter and device allowed_uuid functions
mcap: add adapter authorization
core: block not allowed UUID connect in auth
core: add device_added and device_removed to adapter driver
plugins: new plugin
plugins/admin_policy: add admin_policy adapter driver
plugins/admin_policy: add ServiceAllowList method
plugins/admin_policy: add ServiceAllowList property
plugins/admin_policy: add device callbacks
plugins/admin_policy: add AffectedByPolicy property
plugins/admin_policy: persist policy settings
doc: add description of admin policy

Makefile.plugins | 5 +
bootstrap-configure | 1 +
configure.ac | 4 +
doc/admin-policy-api.txt | 65 ++++
plugins/admin.c | 589 +++++++++++++++++++++++++++++++++++
plugins/admin_policy.c | 653 +++++++++++++++++++++++++++++++++++++++
profiles/health/hdp.c | 1 +
profiles/health/mcap.c | 39 ++-
profiles/health/mcap.h | 7 +
src/adapter.c | 154 ++++++++-
src/adapter.h | 12 +
src/device.c | 64 +++-
src/device.h | 2 +
src/profile.c | 12 +
src/service.c | 39 +++
src/service.h | 2 +
tools/mcaptest.c | 2 +-
17 files changed, 1642 insertions(+), 9 deletions(-)
create mode 100644 doc/admin-policy-api.txt
create mode 100644 plugins/admin.c
create mode 100644 plugins/admin_policy.c

--
2.32.0.432.gabb21c7263-goog



2021-07-28 13:17:48

by Yun-hao Chung

[permalink] [raw]
Subject: [Bluez PATCH v3 09/13] plugins/admin_policy: add ServiceAllowList property

From: Yun-Hao Chung <[email protected]>

This adds code to register interface org.bluez.AdminPolicyStatus.
The interface will provide read-only properties to indicate the current
settings of admin policies. We separate this from AdminPolicySet so that
normal clients can check current policy settings while only a few
clients can change policies.

This patch also adds readonly property ServiceAllowlist to
AdminPolicyStatus1, which indicates the current setting of service
allowlist.

Reviewed-by: Miao-chen Chou <[email protected]>
---
The following test steps were performed:
1. Set ServiceAllowList to ["1124","180A","180F","1812"]
2. Verify ServiceAllowList is ["1124","180A","180F","1812"] in UUID-128
form
3. Set ServiceAllowList to []
4. Verify ServiceAllowList is []

(no changes since v1)

plugins/admin.c | 58 ++++++++++++++++++++++++++++++++++++++++++
plugins/admin_policy.c | 58 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+)

diff --git a/plugins/admin.c b/plugins/admin.c
index 1fe2904d9..d89a77c8a 100644
--- a/plugins/admin.c
+++ b/plugins/admin.c
@@ -27,6 +27,7 @@
#include "src/shared/queue.h"

#define ADMIN_POLICY_SET_INTERFACE "org.bluez.AdminPolicySet1"
+#define ADMIN_POLICY_STATUS_INTERFACE "org.bluez.AdminPolicyStatus1"

static DBusConnection *dbus_conn;

@@ -151,6 +152,11 @@ static DBusMessage *set_service_allowlist(DBusConnection *conn,
return btd_error_failed(msg, "service_allowlist_set failed");
}

+ g_dbus_emit_property_changed(dbus_conn,
+ adapter_get_path(policy_data->adapter),
+ ADMIN_POLICY_STATUS_INTERFACE,
+ "ServiceAllowList");
+
return dbus_message_new_method_return(msg);
}

@@ -160,6 +166,43 @@ static const GDBusMethodTable admin_policy_adapter_methods[] = {
{ }
};

+void append_service_uuid(void *data, void *user_data)
+{
+ bt_uuid_t *uuid = data;
+ DBusMessageIter *entry = user_data;
+ char uuid_str[MAX_LEN_UUID_STR];
+ const char *uuid_str_ptr = uuid_str;
+
+ if (!uuid) {
+ error("Unexpected NULL uuid data in service_allowlist");
+ return;
+ }
+
+ bt_uuid_to_string(uuid, uuid_str, MAX_LEN_UUID_STR);
+ dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &uuid_str_ptr);
+}
+
+static gboolean property_get_service_allowlist(
+ const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct btd_admin_policy *admin_policy = user_data;
+ DBusMessageIter entry;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &entry);
+ queue_foreach(admin_policy->service_allowlist, append_service_uuid,
+ &entry);
+ dbus_message_iter_close_container(iter, &entry);
+
+ return TRUE;
+}
+
+static const GDBusPropertyTable admin_policy_adapter_properties[] = {
+ { "ServiceAllowList", "as", property_get_service_allowlist },
+ { }
+};
+
static int admin_policy_adapter_probe(struct btd_adapter *adapter)
{
const char *adapter_path;
@@ -189,6 +232,21 @@ static int admin_policy_adapter_probe(struct btd_adapter *adapter)

btd_info(policy_data->adapter_id,
"Admin Policy Set interface registered");
+
+ if (!g_dbus_register_interface(dbus_conn, adapter_path,
+ ADMIN_POLICY_STATUS_INTERFACE,
+ NULL, NULL,
+ admin_policy_adapter_properties,
+ policy_data, admin_policy_free)) {
+ btd_error(policy_data->adapter_id,
+ "Admin Policy Status interface init failed on path %s",
+ adapter_path);
+ return -EINVAL;
+ }
+
+ btd_info(policy_data->adapter_id,
+ "Admin Policy Status interface registered");
+
return 0;
}

diff --git a/plugins/admin_policy.c b/plugins/admin_policy.c
index 242b8d5da..270d42366 100644
--- a/plugins/admin_policy.c
+++ b/plugins/admin_policy.c
@@ -27,6 +27,7 @@
#include "src/shared/queue.h"

#define ADMIN_POLICY_SET_INTERFACE "org.bluez.AdminPolicySet1"
+#define ADMIN_POLICY_STATUS_INTERFACE "org.bluez.AdminPolicyStatus1"

static DBusConnection *dbus_conn;

@@ -151,6 +152,11 @@ static DBusMessage *set_service_allowlist(DBusConnection *conn,
return btd_error_failed(msg, "service_allowlist_set failed");
}

+ g_dbus_emit_property_changed(dbus_conn,
+ adapter_get_path(policy_data->adapter),
+ ADMIN_POLICY_STATUS_INTERFACE,
+ "ServiceAllowList");
+
return dbus_message_new_method_return(msg);
}

@@ -160,6 +166,43 @@ static const GDBusMethodTable admin_policy_adapter_methods[] = {
{ }
};

+void append_service_uuid(void *data, void *user_data)
+{
+ bt_uuid_t *uuid = data;
+ DBusMessageIter *entry = user_data;
+ char uuid_str[MAX_LEN_UUID_STR];
+ const char *uuid_str_ptr = uuid_str;
+
+ if (!uuid) {
+ error("Unexpected NULL uuid data in service_allowlist");
+ return;
+ }
+
+ bt_uuid_to_string(uuid, uuid_str, MAX_LEN_UUID_STR);
+ dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &uuid_str_ptr);
+}
+
+static gboolean property_get_service_allowlist(
+ const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct btd_admin_policy *admin_policy = user_data;
+ DBusMessageIter entry;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &entry);
+ queue_foreach(admin_policy->service_allowlist, append_service_uuid,
+ &entry);
+ dbus_message_iter_close_container(iter, &entry);
+
+ return TRUE;
+}
+
+static const GDBusPropertyTable admin_policy_adapter_properties[] = {
+ { "ServiceAllowList", "as", property_get_service_allowlist },
+ { }
+};
+
static int admin_policy_adapter_probe(struct btd_adapter *adapter)
{
if (policy_data) {
@@ -185,6 +228,21 @@ static int admin_policy_adapter_probe(struct btd_adapter *adapter)

btd_info(policy_data->adapter_id,
"Admin Policy Set interface registered");
+
+ if (!g_dbus_register_interface(dbus_conn, adapter_get_path(adapter),
+ ADMIN_POLICY_STATUS_INTERFACE,
+ NULL, NULL,
+ admin_policy_adapter_properties,
+ policy_data, admin_policy_free)) {
+ btd_error(policy_data->adapter_id,
+ "Admin Policy Status interface init failed on path %s",
+ adapter_get_path(adapter));
+ return -EINVAL;
+ }
+
+ btd_info(policy_data->adapter_id,
+ "Admin Policy Status interface registered");
+
return 0;
}

--
2.32.0.432.gabb21c7263-goog


2021-07-28 13:17:48

by Yun-hao Chung

[permalink] [raw]
Subject: [Bluez PATCH v3 03/13] mcap: add adapter authorization

From: Yun-Hao Chung <[email protected]>

Currently mcap is the only profile that doesn't request adatper
authorization. This patch adds a argument when creating the mcap
instance to set authorize method. The reason why we don't use
btd_request_authorization directly like all other profiles is because
tools/mcaptest includes the profile/health/mcap.h. If we add dependency
to adapter.h in mcap.h, it will make mcaptest depend on adapter and be
not able to build independently.
---

(no changes since v1)

profiles/health/hdp.c | 1 +
profiles/health/mcap.c | 39 +++++++++++++++++++++++++++++++++++++--
profiles/health/mcap.h | 7 +++++++
tools/mcaptest.c | 2 +-
4 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/profiles/health/hdp.c b/profiles/health/hdp.c
index 6bc41946f..efa8955ef 100644
--- a/profiles/health/hdp.c
+++ b/profiles/health/hdp.c
@@ -1347,6 +1347,7 @@ static gboolean update_adapter(struct hdp_adapter *hdp_adapter)
mcl_connected, mcl_reconnected,
mcl_disconnected, mcl_uncached,
NULL, /* CSP is not used by now */
+ btd_request_authorization,
hdp_adapter, &err);
if (hdp_adapter->mi == NULL) {
error("Error creating the MCAP instance: %s", err->message);
diff --git a/profiles/health/mcap.c b/profiles/health/mcap.c
index be13af37a..d4cb69f77 100644
--- a/profiles/health/mcap.c
+++ b/profiles/health/mcap.c
@@ -14,6 +14,7 @@
#endif

#define _GNU_SOURCE
+#include <dbus/dbus.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
@@ -23,6 +24,7 @@
#include <glib.h>

#include "lib/bluetooth.h"
+#include "lib/uuid.h"
#include "bluetooth/l2cap.h"
#include "btio/btio.h"
#include "src/log.h"
@@ -1980,7 +1982,6 @@ static void set_mcl_conf(GIOChannel *chan, struct mcap_mcl *mcl)
mcl->state = MCL_CONNECTED;
mcl->role = MCL_ACCEPTOR;
mcl->req = MCL_AVAILABLE;
- mcl->cc = g_io_channel_ref(chan);
mcl->ctrl |= MCAP_CTRL_STD_OP;

mcap_sync_init(mcl);
@@ -2005,19 +2006,39 @@ static void set_mcl_conf(GIOChannel *chan, struct mcap_mcl *mcl)
mcl->mi->mcl_connected_cb(mcl, mcl->mi->user_data);
}

+static void auth_callback(void *err, void *user_data)
+{
+ struct mcap_mcl *mcl = user_data;
+ DBusError *derr = err;
+
+ if (derr) {
+ error("Access denied: %s", derr->message);
+ goto reject;
+ }
+
+ set_mcl_conf(mcl->cc, mcl);
+ return;
+
+reject:
+ g_io_channel_shutdown(mcl->cc, TRUE, NULL);
+ g_io_channel_unref(mcl->cc);
+}
+
static void connect_mcl_event_cb(GIOChannel *chan, GError *gerr,
gpointer user_data)
{
struct mcap_instance *mi = user_data;
struct mcap_mcl *mcl;
- bdaddr_t dst;
+ bdaddr_t src, dst;
char address[18], srcstr[18];
GError *err = NULL;
+ guint ret;

if (gerr)
return;

bt_io_get(chan, &err,
+ BT_IO_OPT_SOURCE_BDADDR, &src,
BT_IO_OPT_DEST_BDADDR, &dst,
BT_IO_OPT_DEST, address,
BT_IO_OPT_INVALID);
@@ -2044,6 +2065,18 @@ static void connect_mcl_event_cb(GIOChannel *chan, GError *gerr,
mcl->next_mdl = (rand() % MCAP_MDLID_FINAL) + 1;
}

+ mcl->cc = g_io_channel_ref(chan);
+ if (mi->authorize_cb) {
+ ret = mi->authorize_cb(&src, &dst, HDP_UUID, auth_callback,
+ mcl);
+ if (ret != 0)
+ return;
+
+ error("HDP: authorization for device %s failed", address);
+ g_io_channel_unref(mcl->cc);
+ goto drop;
+ }
+
set_mcl_conf(chan, mcl);

return;
@@ -2060,6 +2093,7 @@ struct mcap_instance *mcap_create_instance(const bdaddr_t *src,
mcap_mcl_event_cb mcl_disconnected,
mcap_mcl_event_cb mcl_uncached,
mcap_info_ind_event_cb mcl_sync_info_ind,
+ mcap_authorize_cb authorize_cb,
gpointer user_data,
GError **gerr)
{
@@ -2089,6 +2123,7 @@ struct mcap_instance *mcap_create_instance(const bdaddr_t *src,
mi->mcl_disconnected_cb = mcl_disconnected;
mi->mcl_uncached_cb = mcl_uncached;
mi->mcl_sync_infoind_cb = mcl_sync_info_ind;
+ mi->authorize_cb = authorize_cb;
mi->user_data = user_data;
mi->csp_enabled = FALSE;

diff --git a/profiles/health/mcap.h b/profiles/health/mcap.h
index 5a94c8b63..aa69b0d32 100644
--- a/profiles/health/mcap.h
+++ b/profiles/health/mcap.h
@@ -249,6 +249,11 @@ typedef void (* mcap_sync_set_cb) (struct mcap_mcl *mcl,
GError *err,
gpointer data);

+typedef void mcap_auth_cb(void *err, void *user_data);
+typedef guint (* mcap_authorize_cb) (const bdaddr_t *src, const bdaddr_t *dst,
+ const char *uuid, mcap_auth_cb cb,
+ void *user_data);
+
struct mcap_mdl_cb {
mcap_mdl_event_cb mdl_connected; /* Remote device has created a MDL */
mcap_mdl_event_cb mdl_closed; /* Remote device has closed a MDL */
@@ -271,6 +276,7 @@ struct mcap_instance {
mcap_mcl_event_cb mcl_disconnected_cb; /* MCL disconnected */
mcap_mcl_event_cb mcl_uncached_cb; /* MCL has been removed from MCAP cache */
mcap_info_ind_event_cb mcl_sync_infoind_cb; /* (CSP Master) Received info indication */
+ mcap_authorize_cb authorize_cb; /* Method to request authorization */
gpointer user_data; /* Data to be provided in callbacks */
int ref; /* Reference counter */

@@ -404,6 +410,7 @@ struct mcap_instance *mcap_create_instance(const bdaddr_t *src,
mcap_mcl_event_cb mcl_disconnected,
mcap_mcl_event_cb mcl_uncached,
mcap_info_ind_event_cb mcl_sync_info_ind,
+ mcap_authorize_cb authorize_cb,
gpointer user_data,
GError **gerr);
void mcap_release_instance(struct mcap_instance *mi);
diff --git a/tools/mcaptest.c b/tools/mcaptest.c
index dcef0b908..63ee22149 100644
--- a/tools/mcaptest.c
+++ b/tools/mcaptest.c
@@ -434,7 +434,7 @@ int main(int argc, char *argv[])
mcl_connected, mcl_reconnected,
mcl_disconnected, mcl_uncached,
NULL, /* CSP is not used right now */
- NULL, &err);
+ NULL, NULL, &err);

if (!mcap) {
printf("MCAP instance creation failed %s\n", err->message);
--
2.32.0.432.gabb21c7263-goog


2021-07-28 13:17:48

by Yun-hao Chung

[permalink] [raw]
Subject: [Bluez PATCH v3 08/13] plugins/admin_policy: add ServiceAllowList method

From: Yun-Hao Chung <[email protected]>

This adds code to register interface org.bluez.AdminPolicySet1.
The interface will provide methods to limit users to operate certain
functions of bluez, such as allow/disallow user to taggle adapter power,
or only allow users to connect services in the specified list, etc.

This patch also implements ServiceAllowlist in
org.bluez.AdminPolicySet1.

Reviewed-by: Miao-chen Chou <[email protected]>
---
The following test steps were performed:
1. Set ServiceAllowList to
["1108","110A","110B","110C","110D","110E",
"110F","1112","111E","111F","1203"]
( users are only allowed to connect headset )
2. Turn on paired WF1000XM3, and listen music on Youtube.
3. Turn on paired K830 (LE device), press any key on keyboard.
4. Turn on paired Samsung Bluetooth Keyboard EE-BT550 (BREDR device),
press any key on keyboard.
5. Set ServiceAllowList to
["1124","180A","180F","1812"]
( users are only allowed to connect HID devices )
6. Turn on paired WF1000XM3, and listen music on Youtube.
7. Turn on paired K830 (LE device), press any key on keyboard.
8. Turn on paired Samsung Bluetooth Keyboard EE-BT550 (BREDR device),
press any key on keyboard.
9. Set ServiceAllowList to []
( users are only allowed to connect any device. )
10. Turn on paired WF1000XM3, and listen music on Youtube.
11. Turn on paired K830 (LE device), press any key on keyboard.
12. Turn on paired Samsung Bluetooth Keyboard EE-BT550 (BREDR device),
press any key on keyboard.

Expected results:
Step 2,7,8,9,10,11 should success, and step 3,4,6 should fail.

(no changes since v1)

plugins/admin.c | 127 ++++++++++++++++++++++++++++++++++++++++-
plugins/admin_policy.c | 123 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 248 insertions(+), 2 deletions(-)

diff --git a/plugins/admin.c b/plugins/admin.c
index 923e08cb8..1fe2904d9 100644
--- a/plugins/admin.c
+++ b/plugins/admin.c
@@ -12,19 +12,29 @@
#include <config.h>
#endif

+#include <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
#include "lib/bluetooth.h"
+#include "lib/uuid.h"

#include "src/adapter.h"
+#include "src/dbus-common.h"
#include "src/error.h"
#include "src/log.h"
#include "src/plugin.h"

#include "src/shared/queue.h"

+#define ADMIN_POLICY_SET_INTERFACE "org.bluez.AdminPolicySet1"
+
+static DBusConnection *dbus_conn;
+
/* |policy_data| has the same life cycle as btd_adapter */
static struct btd_admin_policy {
struct btd_adapter *adapter;
uint16_t adapter_id;
+ struct queue *service_allowlist;
} *policy_data = NULL;

static struct btd_admin_policy *admin_policy_new(struct btd_adapter *adapter)
@@ -40,19 +50,120 @@ static struct btd_admin_policy *admin_policy_new(struct btd_adapter *adapter)

admin_policy->adapter = adapter;
admin_policy->adapter_id = btd_adapter_get_index(adapter);
+ admin_policy->service_allowlist = NULL;

return admin_policy;
}

+static void free_service_allowlist(struct queue *q)
+{
+ queue_destroy(q, g_free);
+}
+
static void admin_policy_free(void *data)
{
struct btd_admin_policy *admin_policy = data;

+ free_service_allowlist(admin_policy->service_allowlist);
g_free(admin_policy);
}

+static struct queue *parse_allow_service_list(struct btd_adapter *adapter,
+ DBusMessage *msg)
+{
+ DBusMessageIter iter, arr_iter;
+ struct queue *uuid_list = NULL;
+
+ dbus_message_iter_init(msg, &iter);
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+ return NULL;
+
+ uuid_list = queue_new();
+ dbus_message_iter_recurse(&iter, &arr_iter);
+ do {
+ const int type = dbus_message_iter_get_arg_type(&arr_iter);
+ char *uuid_param;
+ bt_uuid_t *uuid;
+
+ if (type == DBUS_TYPE_INVALID)
+ break;
+
+ if (type != DBUS_TYPE_STRING)
+ goto failed;
+
+ dbus_message_iter_get_basic(&arr_iter, &uuid_param);
+
+ uuid = g_try_malloc(sizeof(*uuid));
+ if (!uuid)
+ goto failed;
+
+ if (bt_string_to_uuid(uuid, uuid_param)) {
+ g_free(uuid);
+ goto failed;
+ }
+
+ queue_push_head(uuid_list, uuid);
+
+ dbus_message_iter_next(&arr_iter);
+ } while (true);
+
+ return uuid_list;
+
+failed:
+ queue_destroy(uuid_list, g_free);
+ return NULL;
+}
+
+static bool service_allowlist_set(struct btd_admin_policy *admin_policy,
+ struct queue *uuid_list)
+{
+ struct btd_adapter *adapter = admin_policy->adapter;
+
+ if (!btd_adapter_set_allowed_uuids(adapter, uuid_list))
+ return false;
+
+ free_service_allowlist(admin_policy->service_allowlist);
+ admin_policy->service_allowlist = uuid_list;
+
+ return true;
+}
+
+static DBusMessage *set_service_allowlist(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ struct btd_admin_policy *admin_policy = user_data;
+ struct btd_adapter *adapter = admin_policy->adapter;
+ struct queue *uuid_list = NULL;
+ const char *sender = dbus_message_get_sender(msg);
+
+ DBG("sender %s", sender);
+
+ /* Parse parameters */
+ uuid_list = parse_allow_service_list(adapter, msg);
+ if (!uuid_list) {
+ btd_error(admin_policy->adapter_id,
+ "Failed on parsing allowed service list");
+ return btd_error_invalid_args(msg);
+ }
+
+ if (!service_allowlist_set(admin_policy, uuid_list)) {
+ free_service_allowlist(uuid_list);
+ return btd_error_failed(msg, "service_allowlist_set failed");
+ }
+
+ return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable admin_policy_adapter_methods[] = {
+ { GDBUS_METHOD("SetServiceAllowList", GDBUS_ARGS({ "UUIDs", "as" }),
+ NULL, set_service_allowlist) },
+ { }
+};
+
static int admin_policy_adapter_probe(struct btd_adapter *adapter)
{
+ const char *adapter_path;
+
if (policy_data) {
btd_warn(policy_data->adapter_id,
"Policy data already exists");
@@ -64,8 +175,20 @@ static int admin_policy_adapter_probe(struct btd_adapter *adapter)
if (!policy_data)
return -ENOMEM;

- btd_info(policy_data->adapter_id, "Admin Policy has been enabled");
+ adapter_path = adapter_get_path(adapter);

+ if (!g_dbus_register_interface(dbus_conn, adapter_path,
+ ADMIN_POLICY_SET_INTERFACE,
+ admin_policy_adapter_methods, NULL,
+ NULL, policy_data, admin_policy_free)) {
+ btd_error(policy_data->adapter_id,
+ "Admin Policy Set interface init failed on path %s",
+ adapter_path);
+ return -EINVAL;
+ }
+
+ btd_info(policy_data->adapter_id,
+ "Admin Policy Set interface registered");
return 0;
}

@@ -79,6 +202,8 @@ static int admin_init(void)
{
DBG("");

+ dbus_conn = btd_get_dbus_connection();
+
return btd_register_adapter_driver(&admin_policy_driver);
}

diff --git a/plugins/admin_policy.c b/plugins/admin_policy.c
index 2ece87156..242b8d5da 100644
--- a/plugins/admin_policy.c
+++ b/plugins/admin_policy.c
@@ -12,19 +12,29 @@
#include <config.h>
#endif

+#include <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
#include "lib/bluetooth.h"
+#include "lib/uuid.h"

#include "src/adapter.h"
+#include "src/dbus-common.h"
#include "src/error.h"
#include "src/log.h"
#include "src/plugin.h"

#include "src/shared/queue.h"

+#define ADMIN_POLICY_SET_INTERFACE "org.bluez.AdminPolicySet1"
+
+static DBusConnection *dbus_conn;
+
/* |policy_data| has the same life cycle as btd_adapter */
static struct btd_admin_policy {
struct btd_adapter *adapter;
uint16_t adapter_id;
+ struct queue *service_allowlist;
} *policy_data = NULL;

static struct btd_admin_policy *admin_policy_new(struct btd_adapter *adapter)
@@ -40,17 +50,116 @@ static struct btd_admin_policy *admin_policy_new(struct btd_adapter *adapter)

admin_policy->adapter = adapter;
admin_policy->adapter_id = btd_adapter_get_index(adapter);
+ admin_policy->service_allowlist = NULL;

return admin_policy;
}

+static void free_service_allowlist(struct queue *q)
+{
+ queue_destroy(q, g_free);
+}
+
static void admin_policy_free(void *data)
{
struct btd_admin_policy *admin_policy = data;

+ free_service_allowlist(admin_policy->service_allowlist);
g_free(admin_policy);
}

+static struct queue *parse_allow_service_list(struct btd_adapter *adapter,
+ DBusMessage *msg)
+{
+ DBusMessageIter iter, arr_iter;
+ struct queue *uuid_list = NULL;
+
+ dbus_message_iter_init(msg, &iter);
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+ return NULL;
+
+ uuid_list = queue_new();
+ dbus_message_iter_recurse(&iter, &arr_iter);
+ do {
+ const int type = dbus_message_iter_get_arg_type(&arr_iter);
+ char *uuid_param;
+ bt_uuid_t *uuid;
+
+ if (type == DBUS_TYPE_INVALID)
+ break;
+
+ if (type != DBUS_TYPE_STRING)
+ goto failed;
+
+ dbus_message_iter_get_basic(&arr_iter, &uuid_param);
+
+ uuid = g_try_malloc(sizeof(*uuid));
+ if (!uuid)
+ goto failed;
+
+ if (bt_string_to_uuid(uuid, uuid_param)) {
+ g_free(uuid);
+ goto failed;
+ }
+
+ queue_push_head(uuid_list, uuid);
+
+ dbus_message_iter_next(&arr_iter);
+ } while (true);
+
+ return uuid_list;
+
+failed:
+ queue_destroy(uuid_list, g_free);
+ return NULL;
+}
+
+static bool service_allowlist_set(struct btd_admin_policy *admin_policy,
+ struct queue *uuid_list)
+{
+ struct btd_adapter *adapter = admin_policy->adapter;
+
+ if (!btd_adapter_set_allowed_uuids(adapter, uuid_list))
+ return false;
+
+ free_service_allowlist(admin_policy->service_allowlist);
+ admin_policy->service_allowlist = uuid_list;
+
+ return true;
+}
+
+static DBusMessage *set_service_allowlist(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ struct btd_admin_policy *admin_policy = user_data;
+ struct btd_adapter *adapter = admin_policy->adapter;
+ struct queue *uuid_list = NULL;
+ const char *sender = dbus_message_get_sender(msg);
+
+ DBG("sender %s", sender);
+
+ /* Parse parameters */
+ uuid_list = parse_allow_service_list(adapter, msg);
+ if (!uuid_list) {
+ btd_error(admin_policy->adapter_id,
+ "Failed on parsing allowed service list");
+ return btd_error_invalid_args(msg);
+ }
+
+ if (!service_allowlist_set(admin_policy, uuid_list)) {
+ free_service_allowlist(uuid_list);
+ return btd_error_failed(msg, "service_allowlist_set failed");
+ }
+
+ return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable admin_policy_adapter_methods[] = {
+ { GDBUS_METHOD("SetServiceAllowList", GDBUS_ARGS({ "UUIDs", "as" }),
+ NULL, set_service_allowlist) },
+ { }
+};
+
static int admin_policy_adapter_probe(struct btd_adapter *adapter)
{
if (policy_data) {
@@ -64,8 +173,18 @@ static int admin_policy_adapter_probe(struct btd_adapter *adapter)
if (!policy_data)
return -ENOMEM;

- btd_info(policy_data->adapter_id, "Admin Policy has been enabled");
+ if (!g_dbus_register_interface(dbus_conn, adapter_get_path(adapter),
+ ADMIN_POLICY_SET_INTERFACE,
+ admin_policy_adapter_methods, NULL,
+ NULL, policy_data, admin_policy_free)) {
+ btd_error(policy_data->adapter_id,
+ "Admin Policy Set interface init failed on path %s",
+ adapter_get_path(adapter));
+ return -EINVAL;
+ }

+ btd_info(policy_data->adapter_id,
+ "Admin Policy Set interface registered");
return 0;
}

@@ -79,6 +198,8 @@ static int admin_policy_init(void)
{
DBG("");

+ dbus_conn = btd_get_dbus_connection();
+
return btd_register_adapter_driver(&admin_policy_driver);
}

--
2.32.0.432.gabb21c7263-goog


2021-07-28 13:19:13

by Yun-hao Chung

[permalink] [raw]
Subject: [Bluez PATCH v3 07/13] plugins/admin_policy: add admin_policy adapter driver

From: Yun-Hao Chung <[email protected]>

This adds code to register admin_policy driver to adapter when
admin_policy plugin is enabled.

The following test steps were performed:
1. restart bluetoothd
2. check if "Admin Policy is enabled" in system log

Reviewed-by: Miao-chen Chou <[email protected]>
---

(no changes since v1)

plugins/admin.c | 67 ++++++++++++++++++++++++++++++++++++++++++
plugins/admin_policy.c | 67 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 134 insertions(+)

diff --git a/plugins/admin.c b/plugins/admin.c
index 42866bcf7..923e08cb8 100644
--- a/plugins/admin.c
+++ b/plugins/admin.c
@@ -12,17 +12,84 @@
#include <config.h>
#endif

+#include "lib/bluetooth.h"
+
+#include "src/adapter.h"
+#include "src/error.h"
#include "src/log.h"
#include "src/plugin.h"

+#include "src/shared/queue.h"
+
+/* |policy_data| has the same life cycle as btd_adapter */
+static struct btd_admin_policy {
+ struct btd_adapter *adapter;
+ uint16_t adapter_id;
+} *policy_data = NULL;
+
+static struct btd_admin_policy *admin_policy_new(struct btd_adapter *adapter)
+{
+ struct btd_admin_policy *admin_policy = NULL;
+
+ admin_policy = g_try_malloc(sizeof(*admin_policy));
+ if (!admin_policy) {
+ btd_error(btd_adapter_get_index(adapter),
+ "Failed to allocate memory for admin_policy");
+ return NULL;
+ }
+
+ admin_policy->adapter = adapter;
+ admin_policy->adapter_id = btd_adapter_get_index(adapter);
+
+ return admin_policy;
+}
+
+static void admin_policy_free(void *data)
+{
+ struct btd_admin_policy *admin_policy = data;
+
+ g_free(admin_policy);
+}
+
+static int admin_policy_adapter_probe(struct btd_adapter *adapter)
+{
+ if (policy_data) {
+ btd_warn(policy_data->adapter_id,
+ "Policy data already exists");
+ admin_policy_free(policy_data);
+ policy_data = NULL;
+ }
+
+ policy_data = admin_policy_new(adapter);
+ if (!policy_data)
+ return -ENOMEM;
+
+ btd_info(policy_data->adapter_id, "Admin Policy has been enabled");
+
+ return 0;
+}
+
+static struct btd_adapter_driver admin_policy_driver = {
+ .name = "admin_policy",
+ .probe = admin_policy_adapter_probe,
+ .resume = NULL,
+};
+
static int admin_init(void)
{
DBG("");
+
+ return btd_register_adapter_driver(&admin_policy_driver);
}

static void admin_exit(void)
{
DBG("");
+
+ btd_unregister_adapter_driver(&admin_policy_driver);
+
+ if (policy_data)
+ admin_policy_free(policy_data);
}

BLUETOOTH_PLUGIN_DEFINE(admin, VERSION,
diff --git a/plugins/admin_policy.c b/plugins/admin_policy.c
index dd8d89736..2ece87156 100644
--- a/plugins/admin_policy.c
+++ b/plugins/admin_policy.c
@@ -12,17 +12,84 @@
#include <config.h>
#endif

+#include "lib/bluetooth.h"
+
+#include "src/adapter.h"
+#include "src/error.h"
#include "src/log.h"
#include "src/plugin.h"

+#include "src/shared/queue.h"
+
+/* |policy_data| has the same life cycle as btd_adapter */
+static struct btd_admin_policy {
+ struct btd_adapter *adapter;
+ uint16_t adapter_id;
+} *policy_data = NULL;
+
+static struct btd_admin_policy *admin_policy_new(struct btd_adapter *adapter)
+{
+ struct btd_admin_policy *admin_policy = NULL;
+
+ admin_policy = g_try_malloc(sizeof(*admin_policy));
+ if (!admin_policy) {
+ btd_error(btd_adapter_get_index(adapter),
+ "Failed to allocate memory for admin_policy");
+ return NULL;
+ }
+
+ admin_policy->adapter = adapter;
+ admin_policy->adapter_id = btd_adapter_get_index(adapter);
+
+ return admin_policy;
+}
+
+static void admin_policy_free(void *data)
+{
+ struct btd_admin_policy *admin_policy = data;
+
+ g_free(admin_policy);
+}
+
+static int admin_policy_adapter_probe(struct btd_adapter *adapter)
+{
+ if (policy_data) {
+ btd_warn(policy_data->adapter_id,
+ "Policy data already exists");
+ admin_policy_free(policy_data);
+ policy_data = NULL;
+ }
+
+ policy_data = admin_policy_new(adapter);
+ if (!policy_data)
+ return -ENOMEM;
+
+ btd_info(policy_data->adapter_id, "Admin Policy has been enabled");
+
+ return 0;
+}
+
+static struct btd_adapter_driver admin_policy_driver = {
+ .name = "admin_policy",
+ .probe = admin_policy_adapter_probe,
+ .resume = NULL,
+};
+
static int admin_policy_init(void)
{
DBG("");
+
+ return btd_register_adapter_driver(&admin_policy_driver);
}

static void admin_policy_exit(void)
{
DBG("");
+
+ btd_unregister_adapter_driver(&admin_policy_driver);
+
+ if (policy_data)
+ admin_policy_free(policy_data);
}

BLUETOOTH_PLUGIN_DEFINE(admin_policy, VERSION,
--
2.32.0.432.gabb21c7263-goog


2021-07-28 13:19:13

by Yun-hao Chung

[permalink] [raw]
Subject: [Bluez PATCH v3 10/13] plugins/admin_policy: add device callbacks

From: Yun-Hao Chung <[email protected]>

This adds callbacks for device added and device removed. It is
necessary for implementation of "AffectedByPolicy" property since it
needs to register an interface for each device object and unregister it
once the device gets removed.

Reviewed-by: Miao-chen Chou <[email protected]>
---
The following test steps were performed:
1. start discovery using UI
2. verify device_data were added by checking system log
3. stop discovery
4. verify device_data were removed after a few seconds by checking
system log

(no changes since v1)

plugins/admin.c | 78 +++++++++++++++++++++
plugins/admin_policy.c | 154 +++++++++++++++++++++++++++++++++++++++--
2 files changed, 228 insertions(+), 4 deletions(-)

diff --git a/plugins/admin.c b/plugins/admin.c
index d89a77c8a..37dae77ac 100644
--- a/plugins/admin.c
+++ b/plugins/admin.c
@@ -20,6 +20,7 @@

#include "src/adapter.h"
#include "src/dbus-common.h"
+#include "src/device.h"
#include "src/error.h"
#include "src/log.h"
#include "src/plugin.h"
@@ -29,7 +30,11 @@
#define ADMIN_POLICY_SET_INTERFACE "org.bluez.AdminPolicySet1"
#define ADMIN_POLICY_STATUS_INTERFACE "org.bluez.AdminPolicyStatus1"

+#define DBUS_BLUEZ_SERVICE "org.bluez"
+#define BTD_DEVICE_INTERFACE "org.bluez.Device1"
+
static DBusConnection *dbus_conn;
+static struct queue *devices; /* List of struct device_data objects */

/* |policy_data| has the same life cycle as btd_adapter */
static struct btd_admin_policy {
@@ -38,6 +43,11 @@ static struct btd_admin_policy {
struct queue *service_allowlist;
} *policy_data = NULL;

+struct device_data {
+ struct btd_device *device;
+ char *path;
+};
+
static struct btd_admin_policy *admin_policy_new(struct btd_adapter *adapter)
{
struct btd_admin_policy *admin_policy = NULL;
@@ -203,6 +213,37 @@ static const GDBusPropertyTable admin_policy_adapter_properties[] = {
{ }
};

+static bool device_data_match(const void *a, const void *b)
+{
+ const struct device_data *data = a;
+ const struct btd_device *dev = b;
+
+ if (!data) {
+ error("Unexpected NULL device_data");
+ return false;
+ }
+
+ return data->device == dev;
+}
+
+static void free_device_data(void *data)
+{
+ struct device_data *device_data = data;
+
+ g_free(device_data->path);
+ g_free(device_data);
+}
+
+static void remove_device_data(void *data)
+{
+ struct device_data *device_data = data;
+
+ DBG("device_data for %s removing", device_data->path);
+
+ queue_remove(devices, device_data);
+ free_device_data(device_data);
+}
+
static int admin_policy_adapter_probe(struct btd_adapter *adapter)
{
const char *adapter_path;
@@ -250,10 +291,45 @@ static int admin_policy_adapter_probe(struct btd_adapter *adapter)
return 0;
}

+static void admin_policy_device_added(struct btd_adapter *adapter,
+ struct btd_device *device)
+{
+ struct device_data *data;
+
+ if (queue_find(devices, device_data_match, device))
+ return;
+
+ data = g_new0(struct device_data, 1);
+ if (!data) {
+ btd_error(btd_adapter_get_index(adapter),
+ "Failed to allocate memory for device_data");
+ return;
+ }
+
+ data->device = device;
+ data->path = g_strdup(device_get_path(device));
+ queue_push_tail(devices, data);
+
+ DBG("device_data for %s added", data->path);
+}
+
+static void admin_policy_device_removed(struct btd_adapter *adapter,
+ struct btd_device *device)
+{
+ struct device_data *data;
+
+ data = queue_find(devices, device_data_match, device);
+
+ if (data)
+ remove_device_data(data);
+}
+
static struct btd_adapter_driver admin_policy_driver = {
.name = "admin_policy",
.probe = admin_policy_adapter_probe,
.resume = NULL,
+ .device_added = admin_policy_device_added,
+ .device_removed = admin_policy_device_removed
};

static int admin_init(void)
@@ -261,6 +337,7 @@ static int admin_init(void)
DBG("");

dbus_conn = btd_get_dbus_connection();
+ devices = queue_new();

return btd_register_adapter_driver(&admin_policy_driver);
}
@@ -270,6 +347,7 @@ static void admin_exit(void)
DBG("");

btd_unregister_adapter_driver(&admin_policy_driver);
+ queue_destroy(devices, free_device_data);

if (policy_data)
admin_policy_free(policy_data);
diff --git a/plugins/admin_policy.c b/plugins/admin_policy.c
index 270d42366..73d695ef9 100644
--- a/plugins/admin_policy.c
+++ b/plugins/admin_policy.c
@@ -20,6 +20,7 @@

#include "src/adapter.h"
#include "src/dbus-common.h"
+#include "src/device.h"
#include "src/error.h"
#include "src/log.h"
#include "src/plugin.h"
@@ -29,7 +30,12 @@
#define ADMIN_POLICY_SET_INTERFACE "org.bluez.AdminPolicySet1"
#define ADMIN_POLICY_STATUS_INTERFACE "org.bluez.AdminPolicyStatus1"

+#define DBUS_BLUEZ_SERVICE "org.bluez"
+#define BTD_DEVICE_INTERFACE "org.bluez.Device1"
+
static DBusConnection *dbus_conn;
+static GDBusClient *dbus_client;
+static struct queue *devices; /* List of struct device_data objects */

/* |policy_data| has the same life cycle as btd_adapter */
static struct btd_admin_policy {
@@ -38,6 +44,11 @@ static struct btd_admin_policy {
struct queue *service_allowlist;
} *policy_data = NULL;

+struct device_data {
+ struct btd_device *device;
+ char *path;
+};
+
static struct btd_admin_policy *admin_policy_new(struct btd_adapter *adapter)
{
struct btd_admin_policy *admin_policy = NULL;
@@ -203,8 +214,122 @@ static const GDBusPropertyTable admin_policy_adapter_properties[] = {
{ }
};

+static bool device_data_match(const void *a, const void *b)
+{
+ const struct device_data *data = a;
+ const struct btd_device *dev = b;
+
+ if (!data) {
+ error("Unexpected NULL device_data");
+ return false;
+ }
+
+ return data->device == dev;
+}
+
+static bool device_data_match_by_path(const void *a, const void *b)
+{
+ const struct device_data *data = a;
+ const char *path = b;
+
+ if (!data) {
+ error("Unexpected NULL device_data");
+ return false;
+ }
+
+ return strcmp(data->path, b) == 0;
+}
+
+static void free_device_data(void *data)
+{
+ struct device_data *device_data = data;
+
+ g_free(device_data->path);
+ g_free(device_data);
+}
+
+static void remove_device_data(void *data)
+{
+ struct device_data *device_data = data;
+
+ DBG("device_data for %s removing", device_data->path);
+
+ queue_remove(devices, device_data);
+ free_device_data(device_data);
+}
+
+static void add_device_data(struct btd_device *device)
+{
+ struct btd_adapter *adapter = device_get_adapter(device);
+ struct device_data *data;
+
+ if (queue_find(devices, device_data_match, device))
+ return;
+
+ data = g_new0(struct device_data, 1);
+ if (!data) {
+ btd_error(btd_adapter_get_index(adapter),
+ "Failed to allocate memory for device_data");
+ return;
+ }
+
+ data->device = device;
+ data->path = g_strdup(device_get_path(device));
+ queue_push_tail(devices, data);
+
+ DBG("device_data for %s added", data->path);
+}
+
+static struct btd_device *find_device_by_proxy(GDBusProxy *proxy)
+{
+ const char *path = g_dbus_proxy_get_path(proxy);
+ const char *iface = g_dbus_proxy_get_interface(proxy);
+ struct btd_device *device;
+
+ if (strcmp(iface, BTD_DEVICE_INTERFACE) != 0)
+ return NULL;
+
+ device = btd_adapter_find_device_by_path(policy_data->adapter, path);
+
+ if (!device) {
+ btd_warn(adapter_get_path(policy_data->adapter),
+ "Device path %s is not found", path);
+ }
+
+ return device;
+}
+
+static void object_added_cb(GDBusProxy *proxy, void *user_data)
+{
+ struct btd_device *device;
+
+ device = find_device_by_proxy(proxy);
+
+ if (!device)
+ return;
+
+ add_device_data(device);
+}
+
+static void object_removed_cb(GDBusProxy *proxy, void *user_data)
+{
+ const char *path = g_dbus_proxy_get_path(proxy);
+ const char *iface = g_dbus_proxy_get_interface(proxy);
+ struct device_data *data;
+
+ if (strcmp(iface, BTD_DEVICE_INTERFACE) != 0)
+ return;
+
+ data = queue_find(devices, device_data_match_by_path, path);
+
+ if (data)
+ remove_device_data(data);
+}
+
static int admin_policy_adapter_probe(struct btd_adapter *adapter)
{
+ const char *adapter_path;
+
if (policy_data) {
btd_warn(policy_data->adapter_id,
"Policy data already exists");
@@ -216,33 +341,43 @@ static int admin_policy_adapter_probe(struct btd_adapter *adapter)
if (!policy_data)
return -ENOMEM;

- if (!g_dbus_register_interface(dbus_conn, adapter_get_path(adapter),
+ adapter_path = adapter_get_path(adapter);
+
+ if (!g_dbus_register_interface(dbus_conn, adapter_path,
ADMIN_POLICY_SET_INTERFACE,
admin_policy_adapter_methods, NULL,
NULL, policy_data, admin_policy_free)) {
btd_error(policy_data->adapter_id,
"Admin Policy Set interface init failed on path %s",
- adapter_get_path(adapter));
+ adapter_path);
return -EINVAL;
}

btd_info(policy_data->adapter_id,
"Admin Policy Set interface registered");

- if (!g_dbus_register_interface(dbus_conn, adapter_get_path(adapter),
+ if (!g_dbus_register_interface(dbus_conn, adapter_path,
ADMIN_POLICY_STATUS_INTERFACE,
NULL, NULL,
admin_policy_adapter_properties,
policy_data, admin_policy_free)) {
btd_error(policy_data->adapter_id,
"Admin Policy Status interface init failed on path %s",
- adapter_get_path(adapter));
+ adapter_path);
return -EINVAL;
}

btd_info(policy_data->adapter_id,
"Admin Policy Status interface registered");

+ dbus_client = g_dbus_client_new(dbus_conn, DBUS_BLUEZ_SERVICE,
+ adapter_path);
+
+ g_dbus_client_set_proxy_handlers(dbus_client, object_added_cb,
+ object_removed_cb, NULL, NULL);
+
+ g_dbus_client_set_ready_watch(dbus_client, NULL, NULL);
+
return 0;
}

@@ -257,6 +392,7 @@ static int admin_policy_init(void)
DBG("");

dbus_conn = btd_get_dbus_connection();
+ devices = queue_new();

return btd_register_adapter_driver(&admin_policy_driver);
}
@@ -266,9 +402,19 @@ static void admin_policy_exit(void)
DBG("");

btd_unregister_adapter_driver(&admin_policy_driver);
+ queue_destroy(devices, free_device_data);

if (policy_data)
admin_policy_free(policy_data);
+
+ if (dbus_client) {
+ g_dbus_client_set_disconnect_watch(dbus_client, NULL, NULL);
+ g_dbus_client_set_proxy_handlers(dbus_client, NULL, NULL, NULL,
+ NULL);
+ g_dbus_client_set_ready_watch(dbus_client, NULL, NULL);
+ g_dbus_client_unref(dbus_client);
+ dbus_client = NULL;
+ }
}

BLUETOOTH_PLUGIN_DEFINE(admin_policy, VERSION,
--
2.32.0.432.gabb21c7263-goog


2021-07-28 17:44:46

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [Bluez PATCH v3 07/13] plugins/admin_policy: add admin_policy adapter driver

Hi Howard,

On Wed, Jul 28, 2021 at 6:16 AM Howard Chung <[email protected]> wrote:
>
> From: Yun-Hao Chung <[email protected]>
>
> This adds code to register admin_policy driver to adapter when
> admin_policy plugin is enabled.
>
> The following test steps were performed:
> 1. restart bluetoothd
> 2. check if "Admin Policy is enabled" in system log
>
> Reviewed-by: Miao-chen Chou <[email protected]>
> ---
>
> (no changes since v1)
>
> plugins/admin.c | 67 ++++++++++++++++++++++++++++++++++++++++++
> plugins/admin_policy.c | 67 ++++++++++++++++++++++++++++++++++++++++++

Looks like the old file still being added, besides you should update
your patch description as well since you still mentioning it as
admin_policy in quite a few of them.

> 2 files changed, 134 insertions(+)
>
> diff --git a/plugins/admin.c b/plugins/admin.c
> index 42866bcf7..923e08cb8 100644
> --- a/plugins/admin.c
> +++ b/plugins/admin.c
> @@ -12,17 +12,84 @@
> #include <config.h>
> #endif
>
> +#include "lib/bluetooth.h"
> +
> +#include "src/adapter.h"
> +#include "src/error.h"
> #include "src/log.h"
> #include "src/plugin.h"
>
> +#include "src/shared/queue.h"
> +
> +/* |policy_data| has the same life cycle as btd_adapter */
> +static struct btd_admin_policy {
> + struct btd_adapter *adapter;
> + uint16_t adapter_id;
> +} *policy_data = NULL;
> +
> +static struct btd_admin_policy *admin_policy_new(struct btd_adapter *adapter)
> +{
> + struct btd_admin_policy *admin_policy = NULL;
> +
> + admin_policy = g_try_malloc(sizeof(*admin_policy));
> + if (!admin_policy) {
> + btd_error(btd_adapter_get_index(adapter),
> + "Failed to allocate memory for admin_policy");
> + return NULL;
> + }
> +
> + admin_policy->adapter = adapter;
> + admin_policy->adapter_id = btd_adapter_get_index(adapter);
> +
> + return admin_policy;
> +}
> +
> +static void admin_policy_free(void *data)
> +{
> + struct btd_admin_policy *admin_policy = data;
> +
> + g_free(admin_policy);
> +}
> +
> +static int admin_policy_adapter_probe(struct btd_adapter *adapter)
> +{
> + if (policy_data) {
> + btd_warn(policy_data->adapter_id,
> + "Policy data already exists");
> + admin_policy_free(policy_data);
> + policy_data = NULL;
> + }
> +
> + policy_data = admin_policy_new(adapter);
> + if (!policy_data)
> + return -ENOMEM;
> +
> + btd_info(policy_data->adapter_id, "Admin Policy has been enabled");
> +
> + return 0;
> +}
> +
> +static struct btd_adapter_driver admin_policy_driver = {
> + .name = "admin_policy",
> + .probe = admin_policy_adapter_probe,
> + .resume = NULL,
> +};
> +
> static int admin_init(void)
> {
> DBG("");
> +
> + return btd_register_adapter_driver(&admin_policy_driver);
> }
>
> static void admin_exit(void)
> {
> DBG("");
> +
> + btd_unregister_adapter_driver(&admin_policy_driver);
> +
> + if (policy_data)
> + admin_policy_free(policy_data);
> }
>
> BLUETOOTH_PLUGIN_DEFINE(admin, VERSION,
> diff --git a/plugins/admin_policy.c b/plugins/admin_policy.c
> index dd8d89736..2ece87156 100644
> --- a/plugins/admin_policy.c
> +++ b/plugins/admin_policy.c
> @@ -12,17 +12,84 @@
> #include <config.h>
> #endif
>
> +#include "lib/bluetooth.h"
> +
> +#include "src/adapter.h"
> +#include "src/error.h"
> #include "src/log.h"
> #include "src/plugin.h"
>
> +#include "src/shared/queue.h"
> +
> +/* |policy_data| has the same life cycle as btd_adapter */
> +static struct btd_admin_policy {
> + struct btd_adapter *adapter;
> + uint16_t adapter_id;
> +} *policy_data = NULL;
> +
> +static struct btd_admin_policy *admin_policy_new(struct btd_adapter *adapter)
> +{
> + struct btd_admin_policy *admin_policy = NULL;
> +
> + admin_policy = g_try_malloc(sizeof(*admin_policy));
> + if (!admin_policy) {
> + btd_error(btd_adapter_get_index(adapter),
> + "Failed to allocate memory for admin_policy");
> + return NULL;
> + }
> +
> + admin_policy->adapter = adapter;
> + admin_policy->adapter_id = btd_adapter_get_index(adapter);
> +
> + return admin_policy;
> +}
> +
> +static void admin_policy_free(void *data)
> +{
> + struct btd_admin_policy *admin_policy = data;
> +
> + g_free(admin_policy);
> +}
> +
> +static int admin_policy_adapter_probe(struct btd_adapter *adapter)
> +{
> + if (policy_data) {
> + btd_warn(policy_data->adapter_id,
> + "Policy data already exists");
> + admin_policy_free(policy_data);
> + policy_data = NULL;
> + }
> +
> + policy_data = admin_policy_new(adapter);
> + if (!policy_data)
> + return -ENOMEM;
> +
> + btd_info(policy_data->adapter_id, "Admin Policy has been enabled");
> +
> + return 0;
> +}
> +
> +static struct btd_adapter_driver admin_policy_driver = {
> + .name = "admin_policy",
> + .probe = admin_policy_adapter_probe,
> + .resume = NULL,
> +};
> +
> static int admin_policy_init(void)
> {
> DBG("");
> +
> + return btd_register_adapter_driver(&admin_policy_driver);
> }
>
> static void admin_policy_exit(void)
> {
> DBG("");
> +
> + btd_unregister_adapter_driver(&admin_policy_driver);
> +
> + if (policy_data)
> + admin_policy_free(policy_data);
> }
>
> BLUETOOTH_PLUGIN_DEFINE(admin_policy, VERSION,
> --
> 2.32.0.432.gabb21c7263-goog
>


--
Luiz Augusto von Dentz