1 /******************************************************************************
2 *
3 * Copyright 2014 Google, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #define LOG_TAG "bt_btif_sock_sdp"
20
21 #include "btif/include/btif_sock_sdp.h"
22
23 #include <bluetooth/log.h>
24
25 #include "bta/include/bta_jv_api.h"
26 #include "bta/include/bta_op_api.h"
27 #include "bta/include/utl.h"
28 #include "bta/pb/bta_pbs_int.h"
29 #include "bta/sys/bta_sys.h"
30 #include "internal_include/bt_target.h"
31 #include "stack/include/bt_types.h"
32 #include "stack/include/bt_uuid16.h"
33 #include "stack/include/sdp_api.h"
34 #include "stack/include/sdpdefs.h"
35 #include "types/bluetooth/uuid.h"
36
37 using namespace bluetooth::legacy::stack::sdp;
38 using namespace bluetooth;
39
40 using bluetooth::Uuid;
41
42 // This module provides an abstraction on top of the lower-level SDP database
43 // code for registration and discovery of various bluetooth sockets.
44 //
45 // This code also provides for on-demand registration of "pre-registered"
46 // services as a backwards compatibility function to third-party applications
47 // expecting a bluez stack.
48
49 // Realm Character Set -- 0 is ASCII
50 #define BTA_PBS_REALM_CHARSET 0
51
52 // Specifies whether or not client's user id is required during obex
53 // authentication
54 #define BTA_PBS_USERID_REQ FALSE
55
56 static const tBTA_PBS_CFG bta_pbs_cfg = {
57 BTA_PBS_REALM_CHARSET, // realm_charset: Server only
58 BTA_PBS_USERID_REQ, // userid_req: Server only
59 (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE), // supported_features
60 BTA_PBS_REPOSIT_LOCAL, // supported_repositories
61 };
62
63 // object format lookup table
64 #define OBEX_PUSH_NUM_FORMATS 7
65
66 static const tBTA_OP_FMT bta_ops_obj_fmt[OBEX_PUSH_NUM_FORMATS] = {
67 BTA_OP_VCARD21_FMT, BTA_OP_VCARD30_FMT, BTA_OP_VCAL_FMT, BTA_OP_ICAL_FMT,
68 BTA_OP_VNOTE_FMT, BTA_OP_VMSG_FMT, BTA_OP_OTHER_FMT};
69
70 // TODO(jtgans): Figure out if we actually need this define. This is ifndef
71 // defined in bt_target.h, but nowhere else, so right now, unless something
72 // overrides this before bt_target.h sets it, it will always be bt_target.h's
73 // version.
74 #ifndef BTUI_OPS_FORMATS
75 #define BTUI_OPS_FORMATS \
76 (BTA_OP_VCARD21_MASK | BTA_OP_VCARD30_MASK | BTA_OP_VCAL_MASK | \
77 BTA_OP_ICAL_MASK | BTA_OP_VNOTE_MASK | BTA_OP_VMSG_MASK | BTA_OP_ANY_MASK)
78 #endif
79
80 #define RESERVED_SCN_PBS 19
81 #define RESERVED_SCN_OPS 12
82
83 #define UUID_MAX_LENGTH 16
84
85 #define SPP_PROFILE_VERSION 0x0102
86
87 // Adds a protocol list and service name (if provided) to an SDP record given by
88 // |sdp_handle|, and marks it as browseable. This is a shortcut for defining a
89 // set of protocols that includes L2CAP, RFCOMM, and optionally OBEX. If
90 // |with_obex| is |true|, then an additional OBEX protocol UUID will be included
91 // at the end of the protocol list.
92 //
93 // Returns true if successful, otherwise false.
create_base_record(const uint32_t sdp_handle,const char * name,const uint16_t channel,const bool with_obex)94 static bool create_base_record(const uint32_t sdp_handle, const char* name,
95 const uint16_t channel, const bool with_obex) {
96 log::verbose("create_base_record: scn: {}, name: {}, with_obex: {}", channel,
97 name, with_obex);
98
99 // Setup the protocol list and add it.
100 tSDP_PROTOCOL_ELEM proto_list[SDP_MAX_LIST_ELEMS];
101 int num_proto_elements = with_obex ? 3 : 2;
102
103 memset(proto_list, 0, num_proto_elements * sizeof(tSDP_PROTOCOL_ELEM));
104
105 proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
106 proto_list[0].num_params = 0;
107 proto_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
108 proto_list[1].num_params = 1;
109 proto_list[1].params[0] = channel;
110
111 if (with_obex) {
112 proto_list[2].protocol_uuid = UUID_PROTOCOL_OBEX;
113 proto_list[2].num_params = 0;
114 }
115
116 // Mark the service as browseable.
117 uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
118
119 const char* stage = "protocol_list";
120 if (!get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
121 sdp_handle, num_proto_elements, proto_list))
122 goto error;
123
124 // Add the name to the SDP record.
125 if (name[0] != '\0') {
126 stage = "service_name";
127 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
128 sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
129 (uint32_t)strlen(name), (uint8_t*)name))
130 goto error;
131 }
132
133 stage = "browseable";
134 if (!get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
135 sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list))
136 goto error;
137
138 log::verbose(
139 "create_base_record: successfully created base service record, handle: "
140 "0x{:08x}, scn: {}, name: {}, with_obex: {}",
141 sdp_handle, channel, name, with_obex);
142 return true;
143
144 error:
145 log::error(
146 "create_base_record: failed to create base service record, stage: {}, "
147 "scn: {}, name: {}, with_obex: {}",
148 stage, channel, name, with_obex);
149 return false;
150 }
151
152 // Registers a service with the given |name|, |uuid|, and |channel| in the SDP
153 // database as a generic L2CAP RFCOMM protocol, storing its |uuid| as a service
154 // class sequence.
add_sdp_by_uuid(const char * name,const Uuid & uuid,const uint16_t channel)155 static int add_sdp_by_uuid(const char* name, const Uuid& uuid,
156 const uint16_t channel) {
157 log::verbose("uuid: {}, scn: {}, service_name: {}", uuid.ToString(), channel,
158 name);
159
160 uint32_t handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
161 if (handle == 0) {
162 log::error("failed to create sdp record, scn: {}, service_name: {}",
163 channel, name);
164 return 0;
165 }
166
167 // Convert the |uuid| into a big-endian representation and add it as a
168 // sequence.
169 uint8_t type = UUID_DESC_TYPE;
170 uint8_t type_len = UUID_MAX_LENGTH;
171 uint8_t type_buf[48];
172 // Store the address of type buf in a pointer on the stack, so we can pass
173 // a double pointer to SDP_AddSequence
174 uint8_t* type_buf_ptr = type_buf;
175 uint8_t* tmp = type_buf;
176
177 // Create the base SDP record.
178 const char* stage = "create_base_record";
179 if (!create_base_record(handle, name, channel, false /* with_obex */))
180 goto error;
181
182 // Do the conversion to big-endian -- tmp is only used to iterate through the
183 // UUID array in the macro and serves no other purpose as the conversion
184 // macros are not hygenic.
185
186 { ARRAY_TO_BE_STREAM(tmp, uuid.To128BitBE().data(), UUID_MAX_LENGTH); }
187
188 stage = "service_class_sequence";
189 if (!get_legacy_stack_sdp_api()->handle.SDP_AddSequence(
190 handle, (uint16_t)ATTR_ID_SERVICE_CLASS_ID_LIST, 1, &type, &type_len,
191 &type_buf_ptr))
192 goto error;
193
194 log::verbose(
195 "service registered successfully, service_name: {}, handle: 0x{:08x}",
196 name, handle);
197
198 {
199 // Write the custom 128-bit UUID to EIR
200 tBTA_CUSTOM_UUID curr = {uuid, handle};
201 bta_sys_add_cust_uuid(curr);
202 }
203
204 return handle;
205
206 error:
207 if (get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(handle)) {
208 log::warn("Unable to delete SDP record handle:{}", handle);
209 }
210 log::error("failed to register service stage: {}, service_name: {}", stage,
211 name);
212 return 0;
213 }
214
215 // Registers a service with the given |name| and |channel| in the SDP
216 // database as a PBAP protocol.
add_pbap_sdp(const char * name,const int channel)217 static int add_pbap_sdp(const char* name, const int channel) {
218 log::verbose("add_pbap_sdp: scn {}, service_name {}", channel, name);
219
220 uint32_t handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
221 if (handle == 0) {
222 log::error("add_pbap_sdp: failed to create sdp record, service_name: {}",
223 name);
224 return 0;
225 }
226
227 uint16_t service = UUID_SERVCLASS_PBAP_PSE;
228
229 // Create the base SDP record.
230 const char* stage = "create_base_record";
231 if (!create_base_record(handle, name, channel, true /* with_obex */))
232 goto error;
233
234 // Add service class
235 stage = "service_class";
236 if (!get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(handle, 1,
237 &service))
238 goto error;
239
240 // Add in the phone access descriptor
241 stage = "profile_descriptor_list";
242 if (!get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
243 handle, UUID_SERVCLASS_PHONE_ACCESS, BTA_PBS_DEFAULT_VERSION))
244 goto error;
245
246 // Set up our supported repositories
247 stage = "supported_repositories";
248 if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
249 handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, 1,
250 (uint8_t*)&bta_pbs_cfg.supported_repositories))
251 goto error;
252
253 // Notify the system that we've got a new service class UUID.
254 bta_sys_add_uuid(UUID_SERVCLASS_PBAP_PSE);
255 log::verbose(
256 "add_pbap_sdp: service registered successfully, service_name: {}, "
257 "handle: 0x{:08x}",
258 name, handle);
259
260 return handle;
261
262 error:
263 if (get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(handle)) {
264 log::warn("Unable to delete SDP record handle:{}", handle);
265 }
266 log::error(
267 "add_pbap_sdp: failed to register PBAP service, stage: {}, service_name: "
268 "{}",
269 stage, name);
270 return 0;
271 }
272 // Registers a service with the given |name| and |channel| as an OBEX Push
273 // protocol.
add_ops_sdp(const char * name,const int channel)274 static int add_ops_sdp(const char* name, const int channel) {
275 log::verbose("add_ops_sdp: scn {}, service_name {}", channel, name);
276
277 uint32_t handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
278 if (handle == 0) {
279 log::error("add_ops_sdp: failed to create sdp record, service_name: {}",
280 name);
281 return 0;
282 }
283
284 // Add sequence for supported types.
285 uint8_t desc_type[OBEX_PUSH_NUM_FORMATS];
286 uint8_t type_len[OBEX_PUSH_NUM_FORMATS];
287 uint8_t* type_value[OBEX_PUSH_NUM_FORMATS];
288 uint8_t j = 0;
289
290 uint16_t service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
291 tBTA_UTL_COD cod;
292
293 // Create the base SDP record.
294 const char* stage = "create_base_record";
295 if (!create_base_record(handle, name, channel, true /* with_obex */))
296 goto error;
297
298 // Add service class.
299 stage = "service_class";
300 if (!get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(handle, 1,
301 &service))
302 goto error;
303
304 // Add the OBEX push profile descriptor.
305 stage = "profile_descriptor_list";
306 if (!get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
307 handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH, 0x0100))
308 goto error;
309
310 for (int i = 0; i < OBEX_PUSH_NUM_FORMATS; i++) {
311 if ((BTUI_OPS_FORMATS >> i) & 1) {
312 type_value[j] = (uint8_t*)(&bta_ops_obj_fmt[i]);
313 desc_type[j] = UINT_DESC_TYPE;
314 type_len[j++] = 1;
315 }
316 }
317
318 stage = "supported_types";
319 if (!get_legacy_stack_sdp_api()->handle.SDP_AddSequence(
320 handle, (uint16_t)ATTR_ID_SUPPORTED_FORMATS_LIST, j, desc_type,
321 type_len, type_value))
322 goto error;
323
324 // Set class of device.
325 cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
326 stage = "class_of_device";
327 if (!utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS)) goto error;
328
329 // Notify the system that we've got a new service class UUID.
330 bta_sys_add_uuid(UUID_SERVCLASS_OBEX_OBJECT_PUSH);
331 log::verbose(
332 "ad_maps_sdp: service registered successfully, service_name: {}, handle "
333 "0x{:08x})",
334 name, handle);
335
336 return handle;
337
338 error:
339 if (get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(handle)) {
340 log::warn("Unable to delete SDP record handle:{}", handle);
341 }
342 log::error(
343 "add_ops_sdp: failed to register OPS service, stage: {}, service_name: "
344 "{}",
345 stage, name);
346 return 0;
347 }
348
349 // Registers a service with the given |name| and |channel| as a serial port
350 // profile protocol.
add_spp_sdp(const char * name,const int channel)351 static int add_spp_sdp(const char* name, const int channel) {
352 log::verbose("add_spp_sdp: scn {}, service_name {}", channel, name);
353
354 int handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
355 if (handle == 0) {
356 log::error("add_spp_sdp: failed to create sdp record, service_name: {}",
357 name);
358 return 0;
359 }
360
361 // Create the base SDP record.
362 const char* stage = "create_base_record";
363 uint16_t service = UUID_SERVCLASS_SERIAL_PORT;
364
365 if (!create_base_record(handle, name, channel, false /* with_obex */))
366 goto error;
367
368 stage = "service_class";
369 if (!get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(handle, 1,
370 &service))
371 goto error;
372
373 stage = "profile_descriptor_list";
374 if (!get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
375 handle, UUID_SERVCLASS_SERIAL_PORT, SPP_PROFILE_VERSION))
376 goto error;
377
378 log::verbose(
379 "add_spp_sdp: service registered successfully, service_name: {}, handle "
380 "0x{:08x})",
381 name, handle);
382
383 return handle;
384
385 error:
386 if (get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(handle)) {
387 log::warn("Unable to delete SDP record handle:{}", handle);
388 }
389 log::error(
390 "add_spp_sdp: failed to register SPP service, stage: {}, service_name: "
391 "{}",
392 stage, name);
393 return 0;
394 }
395
396 // Adds an RFCOMM SDP record for a service with the given |name|, |uuid|, and
397 // |channel|. This function attempts to identify the type of the service based
398 // upon its |uuid|, and will override the |channel| with a reserved channel
399 // number if the |uuid| matches one of the preregistered bluez SDP records.
add_rfc_sdp_by_uuid(const char * name,const Uuid & uuid,const int channel)400 static int add_rfc_sdp_by_uuid(const char* name, const Uuid& uuid,
401 const int channel) {
402 log::verbose("uuid: {}, service_name: {}, channel: {}", uuid.ToString(), name,
403 channel);
404
405 /*
406 * Bluetooth Socket API relies on having preregistered bluez sdp records for
407 * HSAG, HFAG, OPP & PBAP that are mapped to rc chan 10, 11,12 & 19. Today
408 * HSAG and HFAG is routed to BRCM AG and are not using BT socket API so for
409 * now we will need to support OPP and PBAP to enable 3rd party developer apps
410 * running on BRCM Android.
411 *
412 * To do this we will check the UUID for the requested service and mimic the
413 * SDP records of bluez upon reception. See functions add_opush() and
414 * add_pbap() in sdptool.c for actual records.
415 */
416
417 int final_channel = get_reserved_rfc_channel(uuid);
418
419 if (final_channel == -1) {
420 final_channel = channel;
421 }
422
423 int handle = 0;
424
425 if (uuid == UUID_OBEX_OBJECT_PUSH) {
426 handle = add_ops_sdp(name, final_channel);
427 } else if (uuid == UUID_PBAP_PSE) {
428 // PBAP Server is always channel 19
429 handle = add_pbap_sdp(name, final_channel);
430 } else if (uuid == UUID_SPP) {
431 handle = add_spp_sdp(name, final_channel);
432 } else if (uuid == UUID_MAP_MAS) {
433 // Record created by new SDP create record interface
434 handle = 0xff;
435 } else {
436 handle = add_sdp_by_uuid(name, uuid, final_channel);
437 }
438
439 return handle;
440 }
441
is_reserved_rfc_channel(const int channel)442 bool is_reserved_rfc_channel(const int channel) {
443 switch (channel) {
444 case RESERVED_SCN_PBS:
445 case RESERVED_SCN_OPS:
446 return true;
447 }
448
449 return false;
450 }
451
get_reserved_rfc_channel(const bluetooth::Uuid & uuid)452 int get_reserved_rfc_channel(const bluetooth::Uuid& uuid) {
453 if (uuid == UUID_PBAP_PSE) {
454 return RESERVED_SCN_PBS;
455 } else if (uuid == UUID_OBEX_OBJECT_PUSH) {
456 return RESERVED_SCN_OPS;
457 }
458
459 return -1;
460 }
461
462 // Adds an SDP record to the SDP database using the given |name|, |uuid|, and
463 // |channel|. Note that if the |uuid| is empty, the |uuid| will be set based
464 // upon the |channel| passed in.
add_rfc_sdp_rec(const char * name,Uuid uuid,const int channel)465 int add_rfc_sdp_rec(const char* name, Uuid uuid, const int channel) {
466 if (uuid.IsEmpty()) {
467 switch (channel) {
468 case RESERVED_SCN_PBS: // PBAP Reserved port
469 uuid = UUID_PBAP_PSE;
470 break;
471
472 case RESERVED_SCN_OPS:
473 uuid = UUID_OBEX_OBJECT_PUSH;
474 break;
475
476 default:
477 uuid = UUID_SPP;
478 break;
479 }
480 }
481
482 return add_rfc_sdp_by_uuid(name, uuid, channel);
483 }
484
485 // Deletes an SDP record with the given |handle|.
del_rfc_sdp_rec(int handle)486 void del_rfc_sdp_rec(int handle) {
487 log::verbose("del_rfc_sdp_rec: handle:0x{:x}", handle);
488
489 if ((handle != -1) && (handle != 0)) {
490 // Remove the custom 128-bit UUID from EIR
491 const tBTA_CUSTOM_UUID curr = {Uuid::kEmpty, (uint32_t)handle};
492 bta_sys_remove_cust_uuid(curr);
493
494 BTA_JvDeleteRecord(handle);
495 }
496 }
497