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