This implements the logics of storing ServiceAllowList when the value changed and restoring ServiceAllowList when adapter initialized. The stored information would look like: ServiceAllowList=$UUID128_STRING1;$UUID128_STRING2...... Reviewed-by: Miao-chen Chou <mcchou@xxxxxxxxxxxx> --- src/adapter.c | 103 +++++++++++++++++++++++++++++++++++++++++++++ src/adapter.h | 1 + src/admin_policy.c | 1 + 3 files changed, 105 insertions(+) diff --git a/src/adapter.c b/src/adapter.c index 5531ed0e2246..f03eda2abc17 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -473,13 +473,19 @@ uint8_t btd_adapter_get_address_type(struct btd_adapter *adapter) return adapter->bdaddr_type; } +static char **create_uuid_string_allowlist(GHashTable *allowed_uuid_set, + guint *num_of_uuid); static void store_adapter_info(struct btd_adapter *adapter) { GKeyFile *key_file; + GHashTable *allowed_uuid_set; char filename[PATH_MAX]; char *str; gsize length = 0; gboolean discoverable; + char **uuid_str_arr; + guint num_of_uuid = 0; + int i; key_file = g_key_file_new(); @@ -508,15 +514,36 @@ static void store_adapter_info(struct btd_adapter *adapter) snprintf(filename, PATH_MAX, STORAGEDIR "/%s/settings", btd_adapter_get_storage_dir(adapter)); + if (adapter->admin_policy) { + allowed_uuid_set = btd_admin_policy_allowlist_get( + adapter->admin_policy); + uuid_str_arr = create_uuid_string_allowlist(allowed_uuid_set, + &num_of_uuid); + g_key_file_set_string_list(key_file, "Policy", + "ServiceAllowList", + (const char *const*)uuid_str_arr, num_of_uuid); + } create_file(filename, 0600); + str = g_key_file_to_data(key_file, &length, NULL); g_file_set_contents(filename, str, length, NULL); g_free(str); + for (i = 0; i < num_of_uuid; i++) + g_free(uuid_str_arr[i]); + + g_free(uuid_str_arr); + g_key_file_free(key_file); } +void btd_adapter_store_adapter_info(struct btd_adapter *adapter) +{ + if (adapter) + store_adapter_info(adapter); +} + static void trigger_pairable_timeout(struct btd_adapter *adapter); static void adapter_start(struct btd_adapter *adapter); static void adapter_stop(struct btd_adapter *adapter); @@ -3509,6 +3536,32 @@ void btd_adapter_refresh_is_blocked_by_policy(struct btd_adapter *adapter) NULL); } +static char **create_uuid_string_allowlist(GHashTable *allowed_uuid_set, + guint *num_of_uuid) +{ + int i; + gpointer *uuids; + char **uuid_str_allowlist; + bt_uuid_t *uuid; + + uuids = g_hash_table_get_keys_as_array(allowed_uuid_set, num_of_uuid); + uuid_str_allowlist = g_try_malloc_n(*num_of_uuid, sizeof(char *)); + + if (!uuid_str_allowlist && !num_of_uuid) { + error("Failed to allocate memory for uuid_str_allowlist"); + return NULL; + } + + for (i = 0; i < *num_of_uuid; i++) { + uuid = uuids[i]; + uuid_str_allowlist[i] = g_try_malloc(MAX_LEN_UUID_STR); + bt_uuid_to_string(uuid, uuid_str_allowlist[i], + MAX_LEN_UUID_STR); + } + + return uuid_str_allowlist; +} + static const GDBusMethodTable adapter_methods[] = { { GDBUS_ASYNC_METHOD("StartDiscovery", NULL, NULL, start_discovery) }, { GDBUS_METHOD("SetDiscoveryFilter", @@ -6265,12 +6318,42 @@ static void fix_storage(struct btd_adapter *adapter) textfile_del(filename, "converted"); } +static GHashTable *uuid_list_to_uuid_set(gchar **uuids, gsize num_of_uuid) +{ + int i; + bt_uuid_t *uuid; + GHashTable *uuid_set = g_hash_table_new_full(bt_uuid_hash, + bt_uuid_equal, g_free, NULL); + + if (!uuid_set) + return NULL; + + for (i = 0; i < num_of_uuid; i++) { + uuid = g_try_malloc(sizeof(*uuid)); + + if (!uuid || bt_string_to_uuid(uuid, *uuids)) + goto failed; + + g_hash_table_add(uuid_set, uuid); + uuids++; + } + + return uuid_set; + +failed: + g_hash_table_destroy(uuid_set); + return NULL; +} + static void load_config(struct btd_adapter *adapter) { GKeyFile *key_file; char filename[PATH_MAX]; struct stat st; + GHashTable *uuid_set; GError *gerr = NULL; + gchar **uuids = NULL; + gsize num_of_uuid; key_file = g_key_file_new(); @@ -6320,6 +6403,23 @@ static void load_config(struct btd_adapter *adapter) gerr = NULL; } + if (adapter->admin_policy) { + uuids = g_key_file_get_string_list(key_file, "Policy", + "ServiceAllowList", &num_of_uuid, &gerr); + + if (gerr) { + uuids = NULL; + num_of_uuid = 0; + g_error_free(gerr); + gerr = NULL; + } + + uuid_set = uuid_list_to_uuid_set(uuids, num_of_uuid); + if (uuid_set) + btd_admin_policy_allowlist_set(adapter->admin_policy, + uuid_set); + } + g_key_file_free(key_file); } @@ -8761,6 +8861,9 @@ load: load_defaults(adapter); load_devices(adapter); + /* Update IsBlockedByPolicy on devices */ + g_slist_foreach(adapter->devices, update_device_is_blocked_by_policy, + NULL); /* restore Service Changed CCC value for bonded devices */ btd_gatt_database_restore_svc_chng_ccc(adapter->database); diff --git a/src/adapter.h b/src/adapter.h index 8e8c61b7bdf1..038754b6d76c 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -90,6 +90,7 @@ const char *adapter_get_path(struct btd_adapter *adapter); const bdaddr_t *btd_adapter_get_address(struct btd_adapter *adapter); uint8_t btd_adapter_get_address_type(struct btd_adapter *adapter); const char *btd_adapter_get_storage_dir(struct btd_adapter *adapter); +void btd_adapter_store_adapter_info(struct btd_adapter *adapter); int adapter_set_name(struct btd_adapter *adapter, const char *name); int adapter_service_add(struct btd_adapter *adapter, sdp_record_t *rec); diff --git a/src/admin_policy.c b/src/admin_policy.c index 6498dcf05319..0b51b379ed74 100644 --- a/src/admin_policy.c +++ b/src/admin_policy.c @@ -154,6 +154,7 @@ static DBusMessage *set_service_allowlist(DBusConnection *conn, g_hash_table_destroy(admin_policy->allowed_uuid_set); btd_admin_policy_allowlist_set(admin_policy, uuid_set); + btd_adapter_store_adapter_info(adapter); return dbus_message_new_method_return(msg); } -- 2.31.0.291.g576ba9dcdaf-goog