1 /** @file
2 * @brief Service Discovery Protocol handling.
3 */
4
5 /*
6 * Copyright (c) 2016 Intel Corporation
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 #include <errno.h>
12 #include <sys/types.h>
13 #include <zephyr/sys/byteorder.h>
14 #include <zephyr/sys/__assert.h>
15
16 #include <zephyr/bluetooth/buf.h>
17 #include <zephyr/bluetooth/sdp.h>
18
19 #include "common/bt_str.h"
20 #include "common/assert.h"
21
22 #include "hci_core.h"
23 #include "conn_internal.h"
24 #include "l2cap_br_internal.h"
25 #include "sdp_internal.h"
26
27 #define LOG_LEVEL CONFIG_BT_SDP_LOG_LEVEL
28 #include <zephyr/logging/log.h>
29 LOG_MODULE_REGISTER(bt_sdp);
30
31 #define SDP_PSM 0x0001
32
33 #define SDP_CHAN(_ch) CONTAINER_OF(_ch, struct bt_sdp, chan.chan)
34
35 #define SDP_DATA_MTU 200
36
37 #define SDP_MTU (SDP_DATA_MTU + sizeof(struct bt_sdp_hdr))
38
39 #define MAX_NUM_ATT_ID_FILTER 10
40
41 #define SDP_SERVICE_HANDLE_BASE 0x10000
42
43 #define SDP_DATA_ELEM_NEST_LEVEL_MAX 5
44
45 /* Size of Cont state length */
46 #define SDP_CONT_STATE_LEN_SIZE 1
47
48 /* 1 byte for the no. of services searched till this response */
49 /* 2 bytes for the total no. of matching records */
50 #define SDP_SS_CONT_STATE_SIZE 3
51
52 /* 1 byte for the no. of attributes searched till this response */
53 #define SDP_SA_CONT_STATE_SIZE 1
54
55 /* 1 byte for the no. of services searched till this response */
56 /* 1 byte for the no. of attributes searched till this response */
57 #define SDP_SSA_CONT_STATE_SIZE 2
58
59 #define SDP_INVALID 0xff
60
61 struct bt_sdp {
62 struct bt_l2cap_br_chan chan;
63 struct k_fifo partial_resp_queue;
64 /* TODO: Allow more than one pending request */
65 };
66
67 static struct bt_sdp_record *db;
68 static uint8_t num_services;
69
70 static struct bt_sdp bt_sdp_pool[CONFIG_BT_MAX_CONN];
71
72 /* Pool for outgoing SDP packets */
73 NET_BUF_POOL_FIXED_DEFINE(sdp_pool, CONFIG_BT_MAX_CONN, BT_L2CAP_BUF_SIZE(SDP_MTU),
74 CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
75
76 #define SDP_CLIENT_CHAN(_ch) CONTAINER_OF(_ch, struct bt_sdp_client, chan.chan)
77
78 #define SDP_CLIENT_MTU 64
79
80 struct bt_sdp_client {
81 struct bt_l2cap_br_chan chan;
82 /* list of waiting to be resolved UUID params */
83 sys_slist_t reqs;
84 /* required SDP transaction ID */
85 uint16_t tid;
86 /* UUID params holder being now resolved */
87 const struct bt_sdp_discover_params *param;
88 /* PDU continuation state object */
89 struct bt_sdp_pdu_cstate cstate;
90 /* buffer for collecting record data */
91 struct net_buf *rec_buf;
92 };
93
94 static struct bt_sdp_client bt_sdp_client_pool[CONFIG_BT_MAX_CONN];
95
96 enum {
97 BT_SDP_ITER_STOP,
98 BT_SDP_ITER_CONTINUE,
99 };
100
101 struct search_state {
102 uint16_t att_list_size;
103 uint8_t current_svc;
104 uint8_t last_att;
105 bool pkt_full;
106 };
107
108 struct select_attrs_data {
109 struct bt_sdp_record *rec;
110 struct net_buf *rsp_buf;
111 struct bt_sdp *sdp;
112 struct bt_sdp_data_elem_seq *seq;
113 struct search_state *state;
114 uint32_t *filter;
115 uint16_t max_att_len;
116 uint16_t att_list_len;
117 uint8_t cont_state_size;
118 uint8_t num_filters;
119 bool new_service;
120 };
121
122 /* @typedef bt_sdp_attr_func_t
123 * @brief SDP attribute iterator callback.
124 *
125 * @param attr Attribute found.
126 * @param att_idx Index of the found attribute in the attribute database.
127 * @param user_data Data given.
128 *
129 * @return BT_SDP_ITER_CONTINUE if should continue to the next attribute
130 * or BT_SDP_ITER_STOP to stop.
131 */
132 typedef uint8_t (*bt_sdp_attr_func_t)(struct bt_sdp_attribute *attr,
133 uint8_t att_idx, void *user_data);
134
135 /* @typedef bt_sdp_svc_func_t
136 * @brief SDP service record iterator callback.
137 *
138 * @param rec Service record found.
139 * @param user_data Data given.
140 *
141 * @return BT_SDP_ITER_CONTINUE if should continue to the next service record
142 * or BT_SDP_ITER_STOP to stop.
143 */
144 typedef uint8_t (*bt_sdp_svc_func_t)(struct bt_sdp_record *rec,
145 void *user_data);
146
147 /* @brief Callback for SDP connection
148 *
149 * Gets called when an SDP connection is established
150 *
151 * @param chan L2CAP channel
152 *
153 * @return None
154 */
bt_sdp_connected(struct bt_l2cap_chan * chan)155 static void bt_sdp_connected(struct bt_l2cap_chan *chan)
156 {
157 struct bt_l2cap_br_chan *ch = CONTAINER_OF(chan,
158 struct bt_l2cap_br_chan,
159 chan);
160
161 struct bt_sdp *sdp = CONTAINER_OF(ch, struct bt_sdp, chan);
162
163 LOG_DBG("chan %p cid 0x%04x", ch, ch->tx.cid);
164
165 k_fifo_init(&sdp->partial_resp_queue);
166 }
167
168 /** @brief Callback for SDP disconnection
169 *
170 * Gets called when an SDP connection is terminated
171 *
172 * @param chan L2CAP channel
173 *
174 * @return None
175 */
bt_sdp_disconnected(struct bt_l2cap_chan * chan)176 static void bt_sdp_disconnected(struct bt_l2cap_chan *chan)
177 {
178 struct bt_l2cap_br_chan *ch = CONTAINER_OF(chan,
179 struct bt_l2cap_br_chan,
180 chan);
181
182 struct bt_sdp *sdp = CONTAINER_OF(ch, struct bt_sdp, chan);
183
184 LOG_DBG("chan %p cid 0x%04x", ch, ch->tx.cid);
185
186 (void)memset(sdp, 0, sizeof(*sdp));
187 }
188
189 /* @brief Creates an SDP PDU
190 *
191 * Creates an empty SDP PDU and returns the buffer
192 *
193 * @param None
194 *
195 * @return Pointer to the net_buf buffer
196 */
bt_sdp_create_pdu(void)197 static struct net_buf *bt_sdp_create_pdu(void)
198 {
199 return bt_l2cap_create_pdu(&sdp_pool, sizeof(struct bt_sdp_hdr));
200 }
201
202 /* @brief Sends out an SDP PDU
203 *
204 * Sends out an SDP PDU after adding the relevant header
205 *
206 * @param chan L2CAP channel
207 * @param buf Buffer to be sent out
208 * @param op Opcode to be used in the packet header
209 * @param tid Transaction ID to be used in the packet header
210 *
211 * @return None
212 */
bt_sdp_send(struct bt_l2cap_chan * chan,struct net_buf * buf,uint8_t op,uint16_t tid)213 static int bt_sdp_send(struct bt_l2cap_chan *chan, struct net_buf *buf,
214 uint8_t op, uint16_t tid)
215 {
216 struct bt_sdp_hdr *hdr;
217 uint16_t param_len = buf->len;
218 int err;
219
220 hdr = net_buf_push(buf, sizeof(struct bt_sdp_hdr));
221 hdr->op_code = op;
222 hdr->tid = tid;
223 hdr->param_len = sys_cpu_to_be16(param_len);
224
225 err = bt_l2cap_chan_send(chan, buf);
226 if (err < 0) {
227 net_buf_unref(buf);
228 }
229
230 return err;
231 }
232
233 /* @brief Sends an error response PDU
234 *
235 * Creates and sends an error response PDU
236 *
237 * @param chan L2CAP channel
238 * @param err Error code to be sent in the packet
239 * @param tid Transaction ID to be used in the packet header
240 *
241 * @return None
242 */
send_err_rsp(struct bt_l2cap_chan * chan,uint16_t err,uint16_t tid)243 static void send_err_rsp(struct bt_l2cap_chan *chan, uint16_t err,
244 uint16_t tid)
245 {
246 struct net_buf *buf;
247
248 LOG_DBG("tid %u, error %u", tid, err);
249
250 buf = bt_sdp_create_pdu();
251
252 net_buf_add_be16(buf, err);
253
254 bt_sdp_send(chan, buf, BT_SDP_ERROR_RSP, tid);
255 }
256
257 /* @brief Parses data elements from a net_buf
258 *
259 * Parses the first data element from a buffer and splits it into type, size,
260 * data. Used for parsing incoming requests. Net buf is advanced to the data
261 * part of the element.
262 *
263 * @param buf Buffer to be advanced
264 * @param data_elem Pointer to the parsed data element structure
265 *
266 * @return 0 for success, or relevant error code
267 */
parse_data_elem(struct net_buf * buf,struct bt_sdp_data_elem * data_elem)268 static uint16_t parse_data_elem(struct net_buf *buf,
269 struct bt_sdp_data_elem *data_elem)
270 {
271 uint8_t size_field_len = 0U; /* Space used to accommodate the size */
272
273 if (buf->len < 1) {
274 LOG_WRN("Malformed packet");
275 return BT_SDP_INVALID_SYNTAX;
276 }
277
278 data_elem->type = net_buf_pull_u8(buf);
279
280 switch (data_elem->type & BT_SDP_TYPE_DESC_MASK) {
281 case BT_SDP_UINT8:
282 case BT_SDP_INT8:
283 case BT_SDP_UUID_UNSPEC:
284 case BT_SDP_BOOL:
285 data_elem->data_size = BIT(data_elem->type &
286 BT_SDP_SIZE_DESC_MASK);
287 break;
288 case BT_SDP_TEXT_STR_UNSPEC:
289 case BT_SDP_SEQ_UNSPEC:
290 case BT_SDP_ALT_UNSPEC:
291 case BT_SDP_URL_STR_UNSPEC:
292 size_field_len = BIT((data_elem->type & BT_SDP_SIZE_DESC_MASK) -
293 BT_SDP_SIZE_INDEX_OFFSET);
294 if (buf->len < size_field_len) {
295 LOG_WRN("Malformed packet");
296 return BT_SDP_INVALID_SYNTAX;
297 }
298 switch (size_field_len) {
299 case 1:
300 data_elem->data_size = net_buf_pull_u8(buf);
301 break;
302 case 2:
303 data_elem->data_size = net_buf_pull_be16(buf);
304 break;
305 case 4:
306 data_elem->data_size = net_buf_pull_be32(buf);
307 break;
308 default:
309 LOG_WRN("Invalid size in remote request");
310 return BT_SDP_INVALID_SYNTAX;
311 }
312 break;
313 default:
314 LOG_WRN("Invalid type in remote request");
315 return BT_SDP_INVALID_SYNTAX;
316 }
317
318 if (buf->len < data_elem->data_size) {
319 LOG_WRN("Malformed packet");
320 return BT_SDP_INVALID_SYNTAX;
321 }
322
323 data_elem->total_size = data_elem->data_size + size_field_len + 1;
324 data_elem->data = buf->data;
325
326 return 0;
327 }
328
329 /* @brief Searches for an UUID within an attribute
330 *
331 * Searches for an UUID within an attribute. If the attribute has data element
332 * sequences, it recursively searches within them as well. On finding a match
333 * with the UUID, it sets the found flag.
334 *
335 * @param elem Attribute to be used as the search space (haystack)
336 * @param uuid UUID to be looked for (needle)
337 * @param found Flag set to true if the UUID is found (to be returned)
338 * @param nest_level Used to limit the extent of recursion into nested data
339 * elements, to avoid potential stack overflows
340 *
341 * @return Size of the last data element that has been searched
342 * (used in recursion)
343 */
search_uuid(struct bt_sdp_data_elem * elem,struct bt_uuid * uuid,bool * found,uint8_t nest_level)344 static uint32_t search_uuid(struct bt_sdp_data_elem *elem, struct bt_uuid *uuid,
345 bool *found, uint8_t nest_level)
346 {
347 const uint8_t *cur_elem;
348 uint32_t seq_size, size;
349 union {
350 struct bt_uuid uuid;
351 struct bt_uuid_16 u16;
352 struct bt_uuid_32 u32;
353 struct bt_uuid_128 u128;
354 } u;
355
356 if (*found) {
357 return 0;
358 }
359
360 /* Limit recursion depth to avoid stack overflows */
361 if (nest_level == SDP_DATA_ELEM_NEST_LEVEL_MAX) {
362 return 0;
363 }
364
365 seq_size = elem->data_size;
366 cur_elem = elem->data;
367
368 if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_UUID_UNSPEC) {
369 if (seq_size == 2U) {
370 u.uuid.type = BT_UUID_TYPE_16;
371 u.u16.val = *((uint16_t *)cur_elem);
372 if (!bt_uuid_cmp(&u.uuid, uuid)) {
373 *found = true;
374 }
375 } else if (seq_size == 4U) {
376 u.uuid.type = BT_UUID_TYPE_32;
377 u.u32.val = *((uint32_t *)cur_elem);
378 if (!bt_uuid_cmp(&u.uuid, uuid)) {
379 *found = true;
380 }
381 } else if (seq_size == 16U) {
382 u.uuid.type = BT_UUID_TYPE_128;
383 memcpy(u.u128.val, cur_elem, seq_size);
384 if (!bt_uuid_cmp(&u.uuid, uuid)) {
385 *found = true;
386 }
387 } else {
388 LOG_WRN("Invalid UUID size in local database");
389 BT_ASSERT(0);
390 }
391 }
392
393 if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_SEQ_UNSPEC ||
394 (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_ALT_UNSPEC) {
395 do {
396 /* Recursively parse data elements */
397 size = search_uuid((struct bt_sdp_data_elem *)cur_elem,
398 uuid, found, nest_level + 1);
399 if (*found) {
400 return 0;
401 }
402 cur_elem += sizeof(struct bt_sdp_data_elem);
403 seq_size -= size;
404 } while (seq_size);
405 }
406
407 return elem->total_size;
408 }
409
410 /* @brief SDP service record iterator.
411 *
412 * Iterate over service records from a starting point.
413 *
414 * @param func Callback function.
415 * @param user_data Data to pass to the callback.
416 *
417 * @return Pointer to the record where the iterator stopped, or NULL if all
418 * records are covered
419 */
bt_sdp_foreach_svc(bt_sdp_svc_func_t func,void * user_data)420 static struct bt_sdp_record *bt_sdp_foreach_svc(bt_sdp_svc_func_t func,
421 void *user_data)
422 {
423 struct bt_sdp_record *rec = db;
424
425 while (rec) {
426 if (func(rec, user_data) == BT_SDP_ITER_STOP) {
427 break;
428 }
429
430 rec = rec->next;
431 }
432 return rec;
433 }
434
435 /* @brief Inserts a service record into a record pointer list
436 *
437 * Inserts a service record into a record pointer list
438 *
439 * @param rec The current service record.
440 * @param user_data Pointer to the destination record list.
441 *
442 * @return BT_SDP_ITER_CONTINUE to move on to the next record.
443 */
insert_record(struct bt_sdp_record * rec,void * user_data)444 static uint8_t insert_record(struct bt_sdp_record *rec, void *user_data)
445 {
446 struct bt_sdp_record **rec_list = user_data;
447
448 rec_list[rec->index] = rec;
449
450 return BT_SDP_ITER_CONTINUE;
451 }
452
453 /* @brief Looks for matching UUIDs in a list of service records
454 *
455 * Parses out a sequence of UUIDs from an input buffer, and checks if a record
456 * in the list contains all the UUIDs. If it doesn't, the record is removed
457 * from the list, so the list contains only the records which has all the
458 * input UUIDs in them.
459 *
460 * @param buf Incoming buffer containing all the UUIDs to be matched
461 * @param matching_recs List of service records to use for storing matching
462 * records
463 *
464 * @return 0 for success, or relevant error code
465 */
find_services(struct net_buf * buf,struct bt_sdp_record ** matching_recs)466 static uint16_t find_services(struct net_buf *buf,
467 struct bt_sdp_record **matching_recs)
468 {
469 struct bt_sdp_data_elem data_elem;
470 struct bt_sdp_record *record;
471 uint32_t uuid_list_size;
472 uint16_t res;
473 uint8_t att_idx, rec_idx = 0U;
474 bool found;
475 union {
476 struct bt_uuid uuid;
477 struct bt_uuid_16 u16;
478 struct bt_uuid_32 u32;
479 struct bt_uuid_128 u128;
480 } u;
481
482 res = parse_data_elem(buf, &data_elem);
483 if (res) {
484 return res;
485 }
486
487 if (((data_elem.type & BT_SDP_TYPE_DESC_MASK) != BT_SDP_SEQ_UNSPEC) &&
488 ((data_elem.type & BT_SDP_TYPE_DESC_MASK) != BT_SDP_ALT_UNSPEC)) {
489 LOG_WRN("Invalid type %x in service search pattern", data_elem.type);
490 return BT_SDP_INVALID_SYNTAX;
491 }
492
493 uuid_list_size = data_elem.data_size;
494
495 bt_sdp_foreach_svc(insert_record, matching_recs);
496
497 /* Go over the sequence of UUIDs, and match one UUID at a time */
498 while (uuid_list_size) {
499 res = parse_data_elem(buf, &data_elem);
500 if (res) {
501 return res;
502 }
503
504 if ((data_elem.type & BT_SDP_TYPE_DESC_MASK) !=
505 BT_SDP_UUID_UNSPEC) {
506 LOG_WRN("Invalid type %u in service search pattern", data_elem.type);
507 return BT_SDP_INVALID_SYNTAX;
508 }
509
510 if (buf->len < data_elem.data_size) {
511 LOG_WRN("Malformed packet");
512 return BT_SDP_INVALID_SYNTAX;
513 }
514
515 if (data_elem.data_size == 2U) {
516 u.uuid.type = BT_UUID_TYPE_16;
517 u.u16.val = net_buf_pull_be16(buf);
518 } else if (data_elem.data_size == 4U) {
519 u.uuid.type = BT_UUID_TYPE_32;
520 u.u32.val = net_buf_pull_be32(buf);
521 } else if (data_elem.data_size == 16U) {
522 u.uuid.type = BT_UUID_TYPE_128;
523 sys_memcpy_swap(u.u128.val, buf->data,
524 data_elem.data_size);
525 net_buf_pull(buf, data_elem.data_size);
526 } else {
527 LOG_WRN("Invalid UUID len %u in service search pattern",
528 data_elem.data_size);
529 net_buf_pull(buf, data_elem.data_size);
530 }
531
532 uuid_list_size -= data_elem.total_size;
533
534 /* Go over the list of services, and look for a service which
535 * doesn't have this UUID
536 */
537 for (rec_idx = 0U; rec_idx < num_services; rec_idx++) {
538 record = matching_recs[rec_idx];
539
540 if (!record) {
541 continue;
542 }
543
544 found = false;
545
546 /* Search for the UUID in all the attrs of the svc */
547 for (att_idx = 0U; att_idx < record->attr_count;
548 att_idx++) {
549 search_uuid(&record->attrs[att_idx].val,
550 &u.uuid, &found, 1);
551 if (found) {
552 break;
553 }
554 }
555
556 /* Remove the record from the list if it doesn't have
557 * the UUID
558 */
559 if (!found) {
560 matching_recs[rec_idx] = NULL;
561 }
562 }
563 }
564
565 return 0;
566 }
567
568 /* @brief Handler for Service Search Request
569 *
570 * Parses, processes and responds to a Service Search Request
571 *
572 * @param sdp Pointer to the SDP structure
573 * @param buf Request net buf
574 * @param tid Transaction ID
575 *
576 * @return 0 for success, or relevant error code
577 */
sdp_svc_search_req(struct bt_sdp * sdp,struct net_buf * buf,uint16_t tid)578 static uint16_t sdp_svc_search_req(struct bt_sdp *sdp, struct net_buf *buf,
579 uint16_t tid)
580 {
581 struct bt_sdp_svc_rsp *rsp;
582 struct net_buf *resp_buf;
583 struct bt_sdp_record *record;
584 struct bt_sdp_record *matching_recs[BT_SDP_MAX_SERVICES];
585 uint16_t max_rec_count, total_recs = 0U, current_recs = 0U, res;
586 uint8_t cont_state_size, cont_state = 0U, idx = 0U, count = 0U;
587 bool pkt_full = false;
588
589 res = find_services(buf, matching_recs);
590 if (res) {
591 /* Error in parsing */
592 return res;
593 }
594
595 if (buf->len < 3) {
596 LOG_WRN("Malformed packet");
597 return BT_SDP_INVALID_SYNTAX;
598 }
599
600 max_rec_count = net_buf_pull_be16(buf);
601 cont_state_size = net_buf_pull_u8(buf);
602
603 /* Zero out the matching services beyond max_rec_count */
604 for (idx = 0U; idx < num_services; idx++) {
605 if (count == max_rec_count) {
606 matching_recs[idx] = NULL;
607 continue;
608 }
609
610 if (matching_recs[idx]) {
611 count++;
612 }
613 }
614
615 /* We send out only SDP_SS_CONT_STATE_SIZE bytes continuation state in
616 * responses, so expect only SDP_SS_CONT_STATE_SIZE bytes in requests
617 */
618 if (cont_state_size) {
619 if (cont_state_size != SDP_SS_CONT_STATE_SIZE) {
620 LOG_WRN("Invalid cont state size %u", cont_state_size);
621 return BT_SDP_INVALID_CSTATE;
622 }
623
624 if (buf->len < cont_state_size) {
625 LOG_WRN("Malformed packet");
626 return BT_SDP_INVALID_SYNTAX;
627 }
628
629 cont_state = net_buf_pull_u8(buf);
630 /* We include total_recs in the continuation state. We calculate
631 * it once and preserve it across all the partial responses
632 */
633 total_recs = net_buf_pull_be16(buf);
634 }
635
636 LOG_DBG("max_rec_count %u, cont_state %u", max_rec_count, cont_state);
637
638 resp_buf = bt_sdp_create_pdu();
639 rsp = net_buf_add(resp_buf, sizeof(*rsp));
640
641 for (; cont_state < num_services; cont_state++) {
642 record = matching_recs[cont_state];
643
644 if (!record) {
645 continue;
646 }
647
648 /* Calculate total recs only if it is first packet */
649 if (!cont_state_size) {
650 total_recs++;
651 }
652
653 if (pkt_full) {
654 continue;
655 }
656
657 /* 4 bytes per Service Record Handle */
658 /* 4 bytes for ContinuationState */
659 if ((MIN(SDP_MTU, sdp->chan.tx.mtu) - resp_buf->len) <
660 (4 + 4 + sizeof(struct bt_sdp_hdr))) {
661 pkt_full = true;
662 }
663
664 if (pkt_full) {
665 /* Packet exhausted: Add continuation state and break */
666 LOG_DBG("Packet full, num_services_covered %u", cont_state);
667 net_buf_add_u8(resp_buf, SDP_SS_CONT_STATE_SIZE);
668 net_buf_add_u8(resp_buf, cont_state);
669
670 /* If it is the first packet of a partial response,
671 * continue dry-running to calculate total_recs.
672 * Else break
673 */
674 if (cont_state_size) {
675 break;
676 }
677
678 continue;
679 }
680
681 /* Add the service record handle to the packet */
682 net_buf_add_be32(resp_buf, record->handle);
683 current_recs++;
684 }
685
686 /* Add 0 continuation state if packet is exhausted */
687 if (!pkt_full) {
688 net_buf_add_u8(resp_buf, 0);
689 } else {
690 net_buf_add_be16(resp_buf, total_recs);
691 }
692
693 rsp->total_recs = sys_cpu_to_be16(total_recs);
694 rsp->current_recs = sys_cpu_to_be16(current_recs);
695
696 LOG_DBG("Sending response, len %u", resp_buf->len);
697 bt_sdp_send(&sdp->chan.chan, resp_buf, BT_SDP_SVC_SEARCH_RSP, tid);
698
699 return 0;
700 }
701
702 /* @brief Copies an attribute into an outgoing buffer
703 *
704 * Copies an attribute into a buffer. Recursively calls itself for complex
705 * attributes.
706 *
707 * @param elem Attribute to be copied to the buffer
708 * @param buf Buffer where the attribute is to be copied
709 *
710 * @return Size of the last data element that has been searched
711 * (used in recursion)
712 */
copy_attribute(struct bt_sdp_data_elem * elem,struct net_buf * buf,uint8_t nest_level)713 static uint32_t copy_attribute(struct bt_sdp_data_elem *elem,
714 struct net_buf *buf, uint8_t nest_level)
715 {
716 const uint8_t *cur_elem;
717 uint32_t size, seq_size, total_size;
718
719 /* Limit recursion depth to avoid stack overflows */
720 if (nest_level == SDP_DATA_ELEM_NEST_LEVEL_MAX) {
721 return 0;
722 }
723
724 seq_size = elem->data_size;
725 total_size = elem->total_size;
726 cur_elem = elem->data;
727
728 /* Copy the header */
729 net_buf_add_u8(buf, elem->type);
730
731 switch (total_size - (seq_size + 1U)) {
732 case 1:
733 net_buf_add_u8(buf, elem->data_size);
734 break;
735 case 2:
736 net_buf_add_be16(buf, elem->data_size);
737 break;
738 case 4:
739 net_buf_add_be32(buf, elem->data_size);
740 break;
741 }
742
743 /* Recursively parse (till the last element is not another data element)
744 * and then fill the elements
745 */
746 if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_SEQ_UNSPEC ||
747 (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_ALT_UNSPEC) {
748 do {
749 size = copy_attribute((struct bt_sdp_data_elem *)
750 cur_elem, buf, nest_level + 1);
751 cur_elem += sizeof(struct bt_sdp_data_elem);
752 seq_size -= size;
753 } while (seq_size);
754 } else if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_UINT8 ||
755 (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_INT8 ||
756 (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_UUID_UNSPEC) {
757 if (seq_size == 1U) {
758 net_buf_add_u8(buf, *((uint8_t *)elem->data));
759 } else if (seq_size == 2U) {
760 net_buf_add_be16(buf, *((uint16_t *)elem->data));
761 } else if (seq_size == 4U) {
762 net_buf_add_be32(buf, *((uint32_t *)elem->data));
763 } else {
764 /* TODO: Convert 32bit and 128bit values to big-endian*/
765 net_buf_add_mem(buf, elem->data, seq_size);
766 }
767 } else {
768 net_buf_add_mem(buf, elem->data, seq_size);
769 }
770
771 return total_size;
772 }
773
774 /* @brief SDP attribute iterator.
775 *
776 * Iterate over attributes of a service record from a starting index.
777 *
778 * @param record Service record whose attributes are to be iterated over.
779 * @param idx Index in the attribute list from where to start.
780 * @param func Callback function.
781 * @param user_data Data to pass to the callback.
782 *
783 * @return Index of the attribute where the iterator stopped
784 */
bt_sdp_foreach_attr(struct bt_sdp_record * record,uint8_t idx,bt_sdp_attr_func_t func,void * user_data)785 static uint8_t bt_sdp_foreach_attr(struct bt_sdp_record *record, uint8_t idx,
786 bt_sdp_attr_func_t func, void *user_data)
787 {
788 for (; idx < record->attr_count; idx++) {
789 if (func(&record->attrs[idx], idx, user_data) ==
790 BT_SDP_ITER_STOP) {
791 break;
792 }
793 }
794
795 return idx;
796 }
797
798 /* @brief Check if an attribute matches a range, and include it in the response
799 *
800 * Checks if an attribute matches a given attribute ID or range, and if so,
801 * includes it in the response packet
802 *
803 * @param attr The current attribute
804 * @param att_idx Index of the current attribute in the database
805 * @param user_data Pointer to the structure containing response packet, byte
806 * count, states, etc
807 *
808 * @return BT_SDP_ITER_CONTINUE if should continue to the next attribute
809 * or BT_SDP_ITER_STOP to stop.
810 */
select_attrs(struct bt_sdp_attribute * attr,uint8_t att_idx,void * user_data)811 static uint8_t select_attrs(struct bt_sdp_attribute *attr, uint8_t att_idx,
812 void *user_data)
813 {
814 struct select_attrs_data *sad = user_data;
815 uint16_t att_id_lower, att_id_upper, att_id_cur, space;
816 uint32_t attr_size, seq_size;
817 uint8_t idx_filter;
818
819 for (idx_filter = 0U; idx_filter < sad->num_filters; idx_filter++) {
820
821 att_id_lower = (sad->filter[idx_filter] >> 16);
822 att_id_upper = (sad->filter[idx_filter]);
823 att_id_cur = attr->id;
824
825 /* Check for range values */
826 if (att_id_lower != 0xffff &&
827 (!IN_RANGE(att_id_cur, att_id_lower, att_id_upper))) {
828 continue;
829 }
830
831 /* Check for match values */
832 if (att_id_lower == 0xffff && att_id_cur != att_id_upper) {
833 continue;
834 }
835
836 /* Attribute ID matches */
837
838 /* 3 bytes for Attribute ID */
839 attr_size = 3 + attr->val.total_size;
840
841 /* If this is the first attribute of the service, then we need
842 * to account for the space required to add the per-service
843 * data element sequence header as well.
844 */
845 if ((sad->state->current_svc != sad->rec->index) &&
846 sad->new_service) {
847 /* 3 bytes for Per-Service Data Elem Seq declaration */
848 seq_size = attr_size + 3;
849 } else {
850 seq_size = attr_size;
851 }
852
853 if (sad->rsp_buf) {
854 space = MIN(SDP_MTU, sad->sdp->chan.tx.mtu) -
855 sad->rsp_buf->len - sizeof(struct bt_sdp_hdr);
856
857 if ((!sad->state->pkt_full) &&
858 ((seq_size > sad->max_att_len) ||
859 (space < seq_size + sad->cont_state_size))) {
860 /* Packet exhausted */
861 sad->state->pkt_full = true;
862 }
863 }
864
865 /* Keep filling data only if packet is not exhausted */
866 if (!sad->state->pkt_full && sad->rsp_buf) {
867 /* Add Per-Service Data Element Seq declaration once
868 * only when we are starting from the first attribute
869 */
870 if (!sad->seq &&
871 (sad->state->current_svc != sad->rec->index)) {
872 sad->seq = net_buf_add(sad->rsp_buf,
873 sizeof(*sad->seq));
874 sad->seq->type = BT_SDP_SEQ16;
875 sad->seq->size = 0U;
876 }
877
878 /* Add attribute ID */
879 net_buf_add_u8(sad->rsp_buf, BT_SDP_UINT16);
880 net_buf_add_be16(sad->rsp_buf, att_id_cur);
881
882 /* Add attribute value */
883 copy_attribute(&attr->val, sad->rsp_buf, 1);
884
885 sad->max_att_len -= seq_size;
886 sad->att_list_len += seq_size;
887 sad->state->last_att = att_idx;
888 sad->state->current_svc = sad->rec->index;
889 }
890
891 if (sad->seq) {
892 /* Keep adding the sequence size if this packet contains
893 * the Per-Service Data Element Seq declaration header
894 */
895 sad->seq->size += attr_size;
896 sad->state->att_list_size += seq_size;
897 } else {
898 /* Keep adding the total attr lists size if:
899 * It's a dry-run, calculating the total attr lists size
900 */
901 sad->state->att_list_size += seq_size;
902 }
903
904 sad->new_service = false;
905 break;
906 }
907
908 /* End the search if:
909 * 1. We have exhausted the packet
910 * AND
911 * 2. This packet doesn't contain the service element declaration header
912 * AND
913 * 3. This is not a dry-run (then we look for other attrs that match)
914 */
915 if (sad->state->pkt_full && !sad->seq && sad->rsp_buf) {
916 return BT_SDP_ITER_STOP;
917 }
918
919 return BT_SDP_ITER_CONTINUE;
920 }
921
922 /* @brief Creates attribute list in the given buffer
923 *
924 * Populates the attribute list of a service record in the buffer. To be used
925 * for responding to Service Attribute and Service Search Attribute requests
926 *
927 * @param sdp Pointer to the SDP structure
928 * @param record Service record whose attributes are to be included in the
929 * response
930 * @param filter Attribute values/ranges to be used as a filter
931 * @param num_filters Number of elements in the attribute filter
932 * @param max_att_len Maximum size of attributes to be included in the response
933 * @param cont_state_size No. of additional continuation state bytes to keep
934 * space for in the packet. This will vary based on the type of the request
935 * @param next_att Starting position of the search in the service's attr list
936 * @param state State of the overall search
937 * @param rsp_buf Response buffer which is filled in
938 *
939 * @return len Length of the attribute list created
940 */
create_attr_list(struct bt_sdp * sdp,struct bt_sdp_record * record,uint32_t * filter,uint8_t num_filters,uint16_t max_att_len,uint8_t cont_state_size,uint8_t next_att,struct search_state * state,struct net_buf * rsp_buf)941 static uint16_t create_attr_list(struct bt_sdp *sdp, struct bt_sdp_record *record,
942 uint32_t *filter, uint8_t num_filters,
943 uint16_t max_att_len, uint8_t cont_state_size,
944 uint8_t next_att, struct search_state *state,
945 struct net_buf *rsp_buf)
946 {
947 struct select_attrs_data sad;
948 uint8_t idx_att;
949
950 sad.num_filters = num_filters;
951 sad.rec = record;
952 sad.rsp_buf = rsp_buf;
953 sad.sdp = sdp;
954 sad.max_att_len = max_att_len;
955 sad.cont_state_size = cont_state_size;
956 sad.seq = NULL;
957 sad.filter = filter;
958 sad.state = state;
959 sad.att_list_len = 0U;
960 sad.new_service = true;
961
962 idx_att = bt_sdp_foreach_attr(sad.rec, next_att, select_attrs, &sad);
963
964 if (sad.seq) {
965 sad.seq->size = sys_cpu_to_be16(sad.seq->size);
966 }
967
968 return sad.att_list_len;
969 }
970
971 /* @brief Extracts the attribute search list from a buffer
972 *
973 * Parses a buffer to extract the attribute search list (list of attribute IDs
974 * and ranges) which are to be used to filter attributes.
975 *
976 * @param buf Buffer to be parsed for extracting the attribute search list
977 * @param filter Empty list of 4byte filters that are filled in. For attribute
978 * IDs, the lower 2 bytes contain the ID and the upper 2 bytes are set to
979 * 0xFFFF. For attribute ranges, the lower 2bytes indicate the start ID and
980 * the upper 2bytes indicate the end ID
981 * @param num_filters No. of filter elements filled in (to be returned)
982 *
983 * @return 0 for success, or relevant error code
984 */
get_att_search_list(struct net_buf * buf,uint32_t * filter,uint8_t * num_filters)985 static uint16_t get_att_search_list(struct net_buf *buf, uint32_t *filter,
986 uint8_t *num_filters)
987 {
988 struct bt_sdp_data_elem data_elem;
989 uint16_t res;
990 uint32_t size;
991
992 *num_filters = 0U;
993 res = parse_data_elem(buf, &data_elem);
994 if (res) {
995 return res;
996 }
997
998 size = data_elem.data_size;
999
1000 while (size) {
1001 res = parse_data_elem(buf, &data_elem);
1002 if (res) {
1003 return res;
1004 }
1005
1006 if ((data_elem.type & BT_SDP_TYPE_DESC_MASK) != BT_SDP_UINT8) {
1007 LOG_WRN("Invalid type %u in attribute ID list", data_elem.type);
1008 return BT_SDP_INVALID_SYNTAX;
1009 }
1010
1011 if (buf->len < data_elem.data_size) {
1012 LOG_WRN("Malformed packet");
1013 return BT_SDP_INVALID_SYNTAX;
1014 }
1015
1016 /* This is an attribute ID */
1017 if (data_elem.data_size == 2U) {
1018 filter[(*num_filters)++] = 0xffff0000 |
1019 net_buf_pull_be16(buf);
1020 }
1021
1022 /* This is an attribute ID range */
1023 if (data_elem.data_size == 4U) {
1024 filter[(*num_filters)++] = net_buf_pull_be32(buf);
1025 }
1026
1027 size -= data_elem.total_size;
1028 }
1029
1030 return 0;
1031 }
1032
1033 /* @brief Check if a given handle matches that of the current service
1034 *
1035 * Checks if a given handle matches that of the current service
1036 *
1037 * @param rec The current service record
1038 * @param user_data Pointer to the service record handle to be matched
1039 *
1040 * @return BT_SDP_ITER_CONTINUE if should continue to the next record
1041 * or BT_SDP_ITER_STOP to stop.
1042 */
find_handle(struct bt_sdp_record * rec,void * user_data)1043 static uint8_t find_handle(struct bt_sdp_record *rec, void *user_data)
1044 {
1045 uint32_t *svc_rec_hdl = user_data;
1046
1047 if (rec->handle == *svc_rec_hdl) {
1048 return BT_SDP_ITER_STOP;
1049 }
1050
1051 return BT_SDP_ITER_CONTINUE;
1052 }
1053
1054 /* @brief Handler for Service Attribute Request
1055 *
1056 * Parses, processes and responds to a Service Attribute Request
1057 *
1058 * @param sdp Pointer to the SDP structure
1059 * @param buf Request buffer
1060 * @param tid Transaction ID
1061 *
1062 * @return 0 for success, or relevant error code
1063 */
sdp_svc_att_req(struct bt_sdp * sdp,struct net_buf * buf,uint16_t tid)1064 static uint16_t sdp_svc_att_req(struct bt_sdp *sdp, struct net_buf *buf,
1065 uint16_t tid)
1066 {
1067 uint32_t filter[MAX_NUM_ATT_ID_FILTER];
1068 struct search_state state = {
1069 .current_svc = SDP_INVALID,
1070 .last_att = SDP_INVALID,
1071 .pkt_full = false
1072 };
1073 struct bt_sdp_record *record;
1074 struct bt_sdp_att_rsp *rsp;
1075 struct net_buf *rsp_buf;
1076 uint32_t svc_rec_hdl;
1077 uint16_t max_att_len, res, att_list_len;
1078 uint8_t num_filters, cont_state_size, next_att = 0U;
1079
1080 if (buf->len < 6) {
1081 LOG_WRN("Malformed packet");
1082 return BT_SDP_INVALID_SYNTAX;
1083 }
1084
1085 svc_rec_hdl = net_buf_pull_be32(buf);
1086 max_att_len = net_buf_pull_be16(buf);
1087
1088 /* Set up the filters */
1089 res = get_att_search_list(buf, filter, &num_filters);
1090 if (res) {
1091 /* Error in parsing */
1092 return res;
1093 }
1094
1095 if (buf->len < 1) {
1096 LOG_WRN("Malformed packet");
1097 return BT_SDP_INVALID_SYNTAX;
1098 }
1099
1100 cont_state_size = net_buf_pull_u8(buf);
1101
1102 /* We only send out 1 byte continuation state in responses,
1103 * so expect only 1 byte in requests
1104 */
1105 if (cont_state_size) {
1106 if (cont_state_size != SDP_SA_CONT_STATE_SIZE) {
1107 LOG_WRN("Invalid cont state size %u", cont_state_size);
1108 return BT_SDP_INVALID_CSTATE;
1109 }
1110
1111 if (buf->len < cont_state_size) {
1112 LOG_WRN("Malformed packet");
1113 return BT_SDP_INVALID_SYNTAX;
1114 }
1115
1116 state.last_att = net_buf_pull_u8(buf) + 1;
1117 next_att = state.last_att;
1118 }
1119
1120 LOG_DBG("svc_rec_hdl %u, max_att_len 0x%04x, cont_state %u", svc_rec_hdl, max_att_len,
1121 next_att);
1122
1123 /* Find the service */
1124 record = bt_sdp_foreach_svc(find_handle, &svc_rec_hdl);
1125
1126 if (!record) {
1127 LOG_WRN("Handle %u not found", svc_rec_hdl);
1128 return BT_SDP_INVALID_RECORD_HANDLE;
1129 }
1130
1131 /* For partial responses, restore the search state */
1132 if (cont_state_size) {
1133 state.current_svc = record->index;
1134 }
1135
1136 rsp_buf = bt_sdp_create_pdu();
1137 rsp = net_buf_add(rsp_buf, sizeof(*rsp));
1138
1139 /* cont_state_size should include 1 byte header */
1140 att_list_len = create_attr_list(sdp, record, filter, num_filters,
1141 max_att_len, SDP_SA_CONT_STATE_SIZE + 1,
1142 next_att, &state, rsp_buf);
1143
1144 if (!att_list_len) {
1145 /* For empty responses, add an empty data element sequence */
1146 net_buf_add_u8(rsp_buf, BT_SDP_SEQ8);
1147 net_buf_add_u8(rsp_buf, 0);
1148 att_list_len = 2U;
1149 }
1150
1151 /* Add continuation state */
1152 if (state.pkt_full) {
1153 LOG_DBG("Packet full, state.last_att %u", state.last_att);
1154 net_buf_add_u8(rsp_buf, 1);
1155 net_buf_add_u8(rsp_buf, state.last_att);
1156 } else {
1157 net_buf_add_u8(rsp_buf, 0);
1158 }
1159
1160 rsp->att_list_len = sys_cpu_to_be16(att_list_len);
1161
1162 LOG_DBG("Sending response, len %u", rsp_buf->len);
1163 bt_sdp_send(&sdp->chan.chan, rsp_buf, BT_SDP_SVC_ATTR_RSP, tid);
1164
1165 return 0;
1166 }
1167
1168 /* @brief Handler for Service Search Attribute Request
1169 *
1170 * Parses, processes and responds to a Service Search Attribute Request
1171 *
1172 * @param sdp Pointer to the SDP structure
1173 * @param buf Request buffer
1174 * @param tid Transaction ID
1175 *
1176 * @return 0 for success, or relevant error code
1177 */
sdp_svc_search_att_req(struct bt_sdp * sdp,struct net_buf * buf,uint16_t tid)1178 static uint16_t sdp_svc_search_att_req(struct bt_sdp *sdp, struct net_buf *buf,
1179 uint16_t tid)
1180 {
1181 uint32_t filter[MAX_NUM_ATT_ID_FILTER];
1182 struct bt_sdp_record *matching_recs[BT_SDP_MAX_SERVICES];
1183 struct search_state state = {
1184 .att_list_size = 0,
1185 .current_svc = SDP_INVALID,
1186 .last_att = SDP_INVALID,
1187 .pkt_full = false
1188 };
1189 struct net_buf *rsp_buf, *rsp_buf_cpy;
1190 struct bt_sdp_record *record;
1191 struct bt_sdp_att_rsp *rsp;
1192 struct bt_sdp_data_elem_seq *seq = NULL;
1193 uint16_t max_att_len, res, att_list_len = 0U;
1194 uint8_t num_filters, cont_state_size, next_svc = 0U, next_att = 0U;
1195 bool dry_run = false;
1196
1197 res = find_services(buf, matching_recs);
1198 if (res) {
1199 return res;
1200 }
1201
1202 if (buf->len < 2) {
1203 LOG_WRN("Malformed packet");
1204 return BT_SDP_INVALID_SYNTAX;
1205 }
1206
1207 max_att_len = net_buf_pull_be16(buf);
1208
1209 /* Set up the filters */
1210 res = get_att_search_list(buf, filter, &num_filters);
1211
1212 if (res) {
1213 /* Error in parsing */
1214 return res;
1215 }
1216
1217 if (buf->len < 1) {
1218 LOG_WRN("Malformed packet");
1219 return BT_SDP_INVALID_SYNTAX;
1220 }
1221
1222 cont_state_size = net_buf_pull_u8(buf);
1223
1224 /* We only send out 2 bytes continuation state in responses,
1225 * so expect only 2 bytes in requests
1226 */
1227 if (cont_state_size) {
1228 if (cont_state_size != SDP_SSA_CONT_STATE_SIZE) {
1229 LOG_WRN("Invalid cont state size %u", cont_state_size);
1230 return BT_SDP_INVALID_CSTATE;
1231 }
1232
1233 if (buf->len < cont_state_size) {
1234 LOG_WRN("Malformed packet");
1235 return BT_SDP_INVALID_SYNTAX;
1236 }
1237
1238 state.current_svc = net_buf_pull_u8(buf);
1239 state.last_att = net_buf_pull_u8(buf) + 1;
1240 next_svc = state.current_svc;
1241 next_att = state.last_att;
1242 }
1243
1244 LOG_DBG("max_att_len 0x%04x, state.current_svc %u, state.last_att %u", max_att_len,
1245 state.current_svc, state.last_att);
1246
1247 rsp_buf = bt_sdp_create_pdu();
1248
1249 rsp = net_buf_add(rsp_buf, sizeof(*rsp));
1250
1251 /* Add headers only if this is not a partial response */
1252 if (!cont_state_size) {
1253 seq = net_buf_add(rsp_buf, sizeof(*seq));
1254 seq->type = BT_SDP_SEQ16;
1255 seq->size = 0U;
1256
1257 /* 3 bytes for Outer Data Element Sequence declaration */
1258 att_list_len = 3U;
1259 }
1260
1261 rsp_buf_cpy = rsp_buf;
1262
1263 for (; next_svc < num_services; next_svc++) {
1264 record = matching_recs[next_svc];
1265
1266 if (!record) {
1267 continue;
1268 }
1269
1270 att_list_len += create_attr_list(sdp, record, filter,
1271 num_filters, max_att_len,
1272 SDP_SSA_CONT_STATE_SIZE + 1,
1273 next_att, &state, rsp_buf_cpy);
1274
1275 /* Check if packet is full and not dry run */
1276 if (state.pkt_full && !dry_run) {
1277 LOG_DBG("Packet full, state.last_att %u", state.last_att);
1278 dry_run = true;
1279
1280 /* Add continuation state */
1281 net_buf_add_u8(rsp_buf, 2);
1282 net_buf_add_u8(rsp_buf, state.current_svc);
1283 net_buf_add_u8(rsp_buf, state.last_att);
1284
1285 /* Break if it's not a partial response, else dry-run
1286 * Dry run: Look for other services that match
1287 */
1288 if (cont_state_size) {
1289 break;
1290 }
1291
1292 rsp_buf_cpy = NULL;
1293 }
1294
1295 next_att = 0U;
1296 }
1297
1298 if (!dry_run) {
1299 if (!att_list_len) {
1300 /* For empty responses, add an empty data elem seq */
1301 net_buf_add_u8(rsp_buf, BT_SDP_SEQ8);
1302 net_buf_add_u8(rsp_buf, 0);
1303 att_list_len = 2U;
1304 }
1305 /* Search exhausted */
1306 net_buf_add_u8(rsp_buf, 0);
1307 }
1308
1309 rsp->att_list_len = sys_cpu_to_be16(att_list_len);
1310 if (seq) {
1311 seq->size = sys_cpu_to_be16(state.att_list_size);
1312 }
1313
1314 LOG_DBG("Sending response, len %u", rsp_buf->len);
1315 bt_sdp_send(&sdp->chan.chan, rsp_buf, BT_SDP_SVC_SEARCH_ATTR_RSP,
1316 tid);
1317
1318 return 0;
1319 }
1320
1321 static const struct {
1322 uint8_t op_code;
1323 uint16_t (*func)(struct bt_sdp *sdp, struct net_buf *buf, uint16_t tid);
1324 } handlers[] = {
1325 { BT_SDP_SVC_SEARCH_REQ, sdp_svc_search_req },
1326 { BT_SDP_SVC_ATTR_REQ, sdp_svc_att_req },
1327 { BT_SDP_SVC_SEARCH_ATTR_REQ, sdp_svc_search_att_req },
1328 };
1329
1330 /* @brief Callback for SDP data receive
1331 *
1332 * Gets called when an SDP PDU is received. Calls the corresponding handler
1333 * based on the op code of the PDU.
1334 *
1335 * @param chan L2CAP channel
1336 * @param buf Received PDU
1337 *
1338 * @return None
1339 */
bt_sdp_recv(struct bt_l2cap_chan * chan,struct net_buf * buf)1340 static int bt_sdp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
1341 {
1342 struct bt_l2cap_br_chan *ch = CONTAINER_OF(chan,
1343 struct bt_l2cap_br_chan, chan);
1344 struct bt_sdp *sdp = CONTAINER_OF(ch, struct bt_sdp, chan);
1345 struct bt_sdp_hdr *hdr;
1346 uint16_t err = BT_SDP_INVALID_SYNTAX;
1347 size_t i;
1348
1349 LOG_DBG("chan %p, ch %p, cid 0x%04x", chan, ch, ch->tx.cid);
1350
1351 BT_ASSERT(sdp);
1352
1353 if (buf->len < sizeof(*hdr)) {
1354 LOG_ERR("Too small SDP PDU received");
1355 return 0;
1356 }
1357
1358 hdr = net_buf_pull_mem(buf, sizeof(*hdr));
1359 LOG_DBG("Received SDP code 0x%02x len %u", hdr->op_code, buf->len);
1360
1361 if (sys_cpu_to_be16(hdr->param_len) != buf->len) {
1362 err = BT_SDP_INVALID_PDU_SIZE;
1363 } else {
1364 for (i = 0; i < ARRAY_SIZE(handlers); i++) {
1365 if (hdr->op_code != handlers[i].op_code) {
1366 continue;
1367 }
1368
1369 err = handlers[i].func(sdp, buf, hdr->tid);
1370 break;
1371 }
1372 }
1373
1374 if (err) {
1375 LOG_WRN("SDP error 0x%02x", err);
1376 send_err_rsp(chan, err, hdr->tid);
1377 }
1378
1379 return 0;
1380 }
1381
1382 /* @brief Callback for SDP connection accept
1383 *
1384 * Gets called when an incoming SDP connection needs to be authorized.
1385 * Registers the L2CAP callbacks and allocates an SDP context to the connection
1386 *
1387 * @param conn BT connection object
1388 * @param chan L2CAP channel structure (to be returned)
1389 *
1390 * @return 0 for success, or relevant error code
1391 */
bt_sdp_accept(struct bt_conn * conn,struct bt_l2cap_server * server,struct bt_l2cap_chan ** chan)1392 static int bt_sdp_accept(struct bt_conn *conn, struct bt_l2cap_server *server,
1393 struct bt_l2cap_chan **chan)
1394 {
1395 static const struct bt_l2cap_chan_ops ops = {
1396 .connected = bt_sdp_connected,
1397 .disconnected = bt_sdp_disconnected,
1398 .recv = bt_sdp_recv,
1399 };
1400 int i;
1401
1402 LOG_DBG("conn %p", conn);
1403
1404 for (i = 0; i < ARRAY_SIZE(bt_sdp_pool); i++) {
1405 struct bt_sdp *sdp = &bt_sdp_pool[i];
1406
1407 if (sdp->chan.chan.conn) {
1408 continue;
1409 }
1410
1411 sdp->chan.chan.ops = &ops;
1412 sdp->chan.rx.mtu = SDP_MTU;
1413
1414 *chan = &sdp->chan.chan;
1415
1416 return 0;
1417 }
1418
1419 LOG_ERR("No available SDP context for conn %p", conn);
1420
1421 return -ENOMEM;
1422 }
1423
bt_sdp_init(void)1424 void bt_sdp_init(void)
1425 {
1426 static struct bt_l2cap_server server = {
1427 .psm = SDP_PSM,
1428 .accept = bt_sdp_accept,
1429 .sec_level = BT_SECURITY_L0,
1430 };
1431 int res;
1432
1433 res = bt_l2cap_br_server_register(&server);
1434 if (res) {
1435 LOG_ERR("L2CAP server registration failed with error %d", res);
1436 }
1437 }
1438
bt_sdp_register_service(struct bt_sdp_record * service)1439 int bt_sdp_register_service(struct bt_sdp_record *service)
1440 {
1441 uint32_t handle = SDP_SERVICE_HANDLE_BASE;
1442
1443 if (!service) {
1444 LOG_ERR("No service record specified");
1445 return 0;
1446 }
1447
1448 if (num_services == BT_SDP_MAX_SERVICES) {
1449 LOG_ERR("Reached max allowed registrations");
1450 return -ENOMEM;
1451 }
1452
1453 if (db) {
1454 handle = db->handle + 1;
1455 }
1456
1457 service->next = db;
1458 service->index = num_services++;
1459 service->handle = handle;
1460 *((uint32_t *)(service->attrs[0].val.data)) = handle;
1461 db = service;
1462
1463 LOG_DBG("Service registered at %u", handle);
1464
1465 return 0;
1466 }
1467
1468 #define GET_PARAM(__node) \
1469 CONTAINER_OF(__node, struct bt_sdp_discover_params, _node)
1470
1471 /* ServiceSearchAttribute PDU, ref to BT Core 4.2, Vol 3, part B, 4.7.1 */
sdp_client_ssa_search(struct bt_sdp_client * session)1472 static int sdp_client_ssa_search(struct bt_sdp_client *session)
1473 {
1474 const struct bt_sdp_discover_params *param;
1475 struct net_buf *buf;
1476
1477 /*
1478 * Select proper user params, if session->param is invalid it means
1479 * getting new UUID from top of to be resolved params list. Otherwise
1480 * the context is in a middle of partial SDP PDU responses and cached
1481 * value from context can be used.
1482 */
1483 if (!session->param) {
1484 param = GET_PARAM(sys_slist_peek_head(&session->reqs));
1485 } else {
1486 param = session->param;
1487 }
1488
1489 if (!param) {
1490 LOG_WRN("No UUIDs to be resolved on remote");
1491 return -EINVAL;
1492 }
1493
1494 buf = bt_sdp_create_pdu();
1495
1496 /* BT_SDP_SEQ8 means length of sequence is on additional next byte */
1497 net_buf_add_u8(buf, BT_SDP_SEQ8);
1498
1499 switch (param->uuid->type) {
1500 case BT_UUID_TYPE_16:
1501 /* Seq length */
1502 net_buf_add_u8(buf, 0x03);
1503 /* Seq type */
1504 net_buf_add_u8(buf, BT_SDP_UUID16);
1505 /* Seq value */
1506 net_buf_add_be16(buf, BT_UUID_16(param->uuid)->val);
1507 break;
1508 case BT_UUID_TYPE_32:
1509 net_buf_add_u8(buf, 0x05);
1510 net_buf_add_u8(buf, BT_SDP_UUID32);
1511 net_buf_add_be32(buf, BT_UUID_32(param->uuid)->val);
1512 break;
1513 case BT_UUID_TYPE_128:
1514 net_buf_add_u8(buf, 0x11);
1515 net_buf_add_u8(buf, BT_SDP_UUID128);
1516 net_buf_add_mem(buf, BT_UUID_128(param->uuid)->val,
1517 ARRAY_SIZE(BT_UUID_128(param->uuid)->val));
1518 break;
1519 default:
1520 LOG_ERR("Unknown UUID type %u", param->uuid->type);
1521 return -EINVAL;
1522 }
1523
1524 /* Set attribute max bytes count to be returned from server */
1525 net_buf_add_be16(buf, BT_SDP_MAX_ATTR_LEN);
1526 /*
1527 * Sequence definition where data is sequence of elements and where
1528 * additional next byte points the size of elements within
1529 */
1530 net_buf_add_u8(buf, BT_SDP_SEQ8);
1531 net_buf_add_u8(buf, 0x05);
1532 /* Data element definition for two following 16bits range elements */
1533 net_buf_add_u8(buf, BT_SDP_UINT32);
1534 /* Get all attributes. It enables filter out wanted only attributes */
1535 net_buf_add_be16(buf, 0x0000);
1536 net_buf_add_be16(buf, 0xffff);
1537
1538 /*
1539 * Update and validate PDU ContinuationState. Initial SSA Request has
1540 * zero length continuation state since no interaction has place with
1541 * server so far, otherwise use the original state taken from remote's
1542 * last response PDU that is cached by SDP client context.
1543 */
1544 if (session->cstate.length == 0U) {
1545 net_buf_add_u8(buf, 0x00);
1546 } else {
1547 net_buf_add_u8(buf, session->cstate.length);
1548 net_buf_add_mem(buf, session->cstate.data,
1549 session->cstate.length);
1550 }
1551
1552 /* Update context param to the one being resolving now */
1553 session->param = param;
1554 session->tid++;
1555
1556 return bt_sdp_send(&session->chan.chan, buf, BT_SDP_SVC_SEARCH_ATTR_REQ,
1557 session->tid);
1558 }
1559
sdp_client_params_iterator(struct bt_sdp_client * session)1560 static void sdp_client_params_iterator(struct bt_sdp_client *session)
1561 {
1562 struct bt_l2cap_chan *chan = &session->chan.chan;
1563 struct bt_sdp_discover_params *param, *tmp;
1564
1565 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&session->reqs, param, tmp, _node) {
1566 if (param != session->param) {
1567 continue;
1568 }
1569
1570 LOG_DBG("");
1571
1572 /* Remove already checked UUID node */
1573 sys_slist_remove(&session->reqs, NULL, ¶m->_node);
1574 /* Invalidate cached param in context */
1575 session->param = NULL;
1576 /* Reset continuation state in current context */
1577 (void)memset(&session->cstate, 0, sizeof(session->cstate));
1578
1579 /* Check if there's valid next UUID */
1580 if (!sys_slist_is_empty(&session->reqs)) {
1581 sdp_client_ssa_search(session);
1582 return;
1583 }
1584
1585 /* No UUID items, disconnect channel */
1586 bt_l2cap_chan_disconnect(chan);
1587 break;
1588 }
1589 }
1590
sdp_client_get_total(struct bt_sdp_client * session,struct net_buf * buf,uint16_t * total)1591 static uint16_t sdp_client_get_total(struct bt_sdp_client *session,
1592 struct net_buf *buf, uint16_t *total)
1593 {
1594 uint16_t pulled;
1595 uint8_t seq;
1596
1597 /*
1598 * Pull value of total octets of all attributes available to be
1599 * collected when response gets completed for given UUID. Such info can
1600 * be get from the very first response frame after initial SSA request
1601 * was sent. For subsequent calls related to the same SSA request input
1602 * buf and in/out function parameters stays neutral.
1603 */
1604 if (session->cstate.length == 0U) {
1605 seq = net_buf_pull_u8(buf);
1606 pulled = 1U;
1607 switch (seq) {
1608 case BT_SDP_SEQ8:
1609 *total = net_buf_pull_u8(buf);
1610 pulled += 1U;
1611 break;
1612 case BT_SDP_SEQ16:
1613 *total = net_buf_pull_be16(buf);
1614 pulled += 2U;
1615 break;
1616 default:
1617 LOG_WRN("Sequence type 0x%02x not handled", seq);
1618 *total = 0U;
1619 break;
1620 }
1621
1622 LOG_DBG("Total %u octets of all attributes", *total);
1623 } else {
1624 pulled = 0U;
1625 *total = 0U;
1626 }
1627
1628 return pulled;
1629 }
1630
get_record_len(struct net_buf * buf)1631 static uint16_t get_record_len(struct net_buf *buf)
1632 {
1633 uint16_t len;
1634 uint8_t seq;
1635
1636 seq = net_buf_pull_u8(buf);
1637
1638 switch (seq) {
1639 case BT_SDP_SEQ8:
1640 len = net_buf_pull_u8(buf);
1641 break;
1642 case BT_SDP_SEQ16:
1643 len = net_buf_pull_be16(buf);
1644 break;
1645 default:
1646 LOG_WRN("Sequence type 0x%02x not handled", seq);
1647 len = 0U;
1648 break;
1649 }
1650
1651 LOG_DBG("Record len %u", len);
1652
1653 return len;
1654 }
1655
1656 enum uuid_state {
1657 UUID_NOT_RESOLVED,
1658 UUID_RESOLVED,
1659 };
1660
sdp_client_notify_result(struct bt_sdp_client * session,enum uuid_state state)1661 static void sdp_client_notify_result(struct bt_sdp_client *session,
1662 enum uuid_state state)
1663 {
1664 struct bt_conn *conn = session->chan.chan.conn;
1665 struct bt_sdp_client_result result;
1666 uint16_t rec_len;
1667 uint8_t user_ret;
1668
1669 result.uuid = session->param->uuid;
1670
1671 if (state == UUID_NOT_RESOLVED) {
1672 result.resp_buf = NULL;
1673 result.next_record_hint = false;
1674 session->param->func(conn, &result);
1675 return;
1676 }
1677
1678 while (session->rec_buf->len) {
1679 struct net_buf_simple_state buf_state;
1680
1681 rec_len = get_record_len(session->rec_buf);
1682 /* tell the user about multi record resolution */
1683 if (session->rec_buf->len > rec_len) {
1684 result.next_record_hint = true;
1685 } else {
1686 result.next_record_hint = false;
1687 }
1688
1689 /* save the original session buffer */
1690 net_buf_simple_save(&session->rec_buf->b, &buf_state);
1691 /* initialize internal result buffer instead of memcpy */
1692 result.resp_buf = session->rec_buf;
1693 /*
1694 * Set user internal result buffer length as same as record
1695 * length to fake user. User will see the individual record
1696 * length as rec_len instead of whole session rec_buf length.
1697 */
1698 result.resp_buf->len = rec_len;
1699
1700 user_ret = session->param->func(conn, &result);
1701
1702 /* restore original session buffer */
1703 net_buf_simple_restore(&session->rec_buf->b, &buf_state);
1704 /*
1705 * sync session buffer data length with next record chunk not
1706 * send to user so far
1707 */
1708 net_buf_pull(session->rec_buf, rec_len);
1709 if (user_ret == BT_SDP_DISCOVER_UUID_STOP) {
1710 break;
1711 }
1712 }
1713 }
1714
sdp_client_receive(struct bt_l2cap_chan * chan,struct net_buf * buf)1715 static int sdp_client_receive(struct bt_l2cap_chan *chan, struct net_buf *buf)
1716 {
1717 struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
1718 struct bt_sdp_hdr *hdr;
1719 struct bt_sdp_pdu_cstate *cstate;
1720 uint16_t len, tid, frame_len;
1721 uint16_t total;
1722
1723 LOG_DBG("session %p buf %p", session, buf);
1724
1725 if (buf->len < sizeof(*hdr)) {
1726 LOG_ERR("Too small SDP PDU");
1727 return 0;
1728 }
1729
1730 hdr = net_buf_pull_mem(buf, sizeof(*hdr));
1731 if (hdr->op_code == BT_SDP_ERROR_RSP) {
1732 LOG_INF("Error SDP PDU response");
1733 return 0;
1734 }
1735
1736 len = sys_be16_to_cpu(hdr->param_len);
1737 tid = sys_be16_to_cpu(hdr->tid);
1738
1739 LOG_DBG("SDP PDU tid %u len %u", tid, len);
1740
1741 if (buf->len != len) {
1742 LOG_ERR("SDP PDU length mismatch (%u != %u)", buf->len, len);
1743 return 0;
1744 }
1745
1746 if (tid != session->tid) {
1747 LOG_ERR("Mismatch transaction ID value in SDP PDU");
1748 return 0;
1749 }
1750
1751 switch (hdr->op_code) {
1752 case BT_SDP_SVC_SEARCH_ATTR_RSP:
1753 /* Get number of attributes in this frame. */
1754 frame_len = net_buf_pull_be16(buf);
1755 /* Check valid buf len for attribute list and cont state */
1756 if (buf->len < frame_len + SDP_CONT_STATE_LEN_SIZE) {
1757 LOG_ERR("Invalid frame payload length");
1758 return 0;
1759 }
1760 /* Check valid range of attributes length */
1761 if (frame_len < 2) {
1762 LOG_ERR("Invalid attributes data length");
1763 return 0;
1764 }
1765
1766 /* Get PDU continuation state */
1767 cstate = (struct bt_sdp_pdu_cstate *)(buf->data + frame_len);
1768
1769 if (cstate->length > BT_SDP_MAX_PDU_CSTATE_LEN) {
1770 LOG_ERR("Invalid SDP PDU Continuation State length %u", cstate->length);
1771 return 0;
1772 }
1773
1774 if ((frame_len + SDP_CONT_STATE_LEN_SIZE + cstate->length) >
1775 buf->len) {
1776 LOG_ERR("Invalid frame payload length");
1777 return 0;
1778 }
1779
1780 /*
1781 * No record found for given UUID. The check catches case when
1782 * current response frame has Continuation State shortest and
1783 * valid and this is the first response frame as well.
1784 */
1785 if (frame_len == 2U && cstate->length == 0U &&
1786 session->cstate.length == 0U) {
1787 LOG_DBG("record for UUID 0x%s not found",
1788 bt_uuid_str(session->param->uuid));
1789 /* Call user UUID handler */
1790 sdp_client_notify_result(session, UUID_NOT_RESOLVED);
1791 net_buf_pull(buf, frame_len + sizeof(cstate->length));
1792 goto iterate;
1793 }
1794
1795 /* Get total value of all attributes to be collected */
1796 frame_len -= sdp_client_get_total(session, buf, &total);
1797
1798 if (total > net_buf_tailroom(session->rec_buf)) {
1799 LOG_WRN("Not enough room for getting records data");
1800 goto iterate;
1801 }
1802
1803 net_buf_add_mem(session->rec_buf, buf->data, frame_len);
1804 net_buf_pull(buf, frame_len);
1805
1806 /*
1807 * check if current response says there's next portion to be
1808 * fetched
1809 */
1810 if (cstate->length) {
1811 /* Cache original Continuation State in context */
1812 memcpy(&session->cstate, cstate,
1813 sizeof(struct bt_sdp_pdu_cstate));
1814
1815 net_buf_pull(buf, cstate->length +
1816 sizeof(cstate->length));
1817
1818 /* Request for next portion of attributes data */
1819 sdp_client_ssa_search(session);
1820 break;
1821 }
1822
1823 net_buf_pull(buf, sizeof(cstate->length));
1824
1825 LOG_DBG("UUID 0x%s resolved", bt_uuid_str(session->param->uuid));
1826 sdp_client_notify_result(session, UUID_RESOLVED);
1827 iterate:
1828 /* Get next UUID and start resolving it */
1829 sdp_client_params_iterator(session);
1830 break;
1831 default:
1832 LOG_DBG("PDU 0x%0x response not handled", hdr->op_code);
1833 break;
1834 }
1835
1836 return 0;
1837 }
1838
sdp_client_chan_connect(struct bt_sdp_client * session)1839 static int sdp_client_chan_connect(struct bt_sdp_client *session)
1840 {
1841 return bt_l2cap_br_chan_connect(session->chan.chan.conn,
1842 &session->chan.chan, SDP_PSM);
1843 }
1844
sdp_client_alloc_buf(struct bt_l2cap_chan * chan)1845 static struct net_buf *sdp_client_alloc_buf(struct bt_l2cap_chan *chan)
1846 {
1847 struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
1848 struct net_buf *buf;
1849
1850 LOG_DBG("session %p chan %p", session, chan);
1851
1852 session->param = GET_PARAM(sys_slist_peek_head(&session->reqs));
1853
1854 buf = net_buf_alloc(session->param->pool, K_FOREVER);
1855 __ASSERT_NO_MSG(buf);
1856
1857 return buf;
1858 }
1859
sdp_client_connected(struct bt_l2cap_chan * chan)1860 static void sdp_client_connected(struct bt_l2cap_chan *chan)
1861 {
1862 struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
1863
1864 LOG_DBG("session %p chan %p connected", session, chan);
1865
1866 session->rec_buf = chan->ops->alloc_buf(chan);
1867
1868 sdp_client_ssa_search(session);
1869 }
1870
sdp_client_disconnected(struct bt_l2cap_chan * chan)1871 static void sdp_client_disconnected(struct bt_l2cap_chan *chan)
1872 {
1873 struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
1874
1875 LOG_DBG("session %p chan %p disconnected", session, chan);
1876
1877 net_buf_unref(session->rec_buf);
1878
1879 /*
1880 * Reset session excluding L2CAP channel member. Let's the channel
1881 * resets autonomous.
1882 */
1883 (void)memset(&session->reqs, 0,
1884 sizeof(*session) - sizeof(session->chan));
1885 }
1886
1887 static const struct bt_l2cap_chan_ops sdp_client_chan_ops = {
1888 .connected = sdp_client_connected,
1889 .disconnected = sdp_client_disconnected,
1890 .recv = sdp_client_receive,
1891 .alloc_buf = sdp_client_alloc_buf,
1892 };
1893
sdp_client_new_session(struct bt_conn * conn)1894 static struct bt_sdp_client *sdp_client_new_session(struct bt_conn *conn)
1895 {
1896 int i;
1897
1898 for (i = 0; i < ARRAY_SIZE(bt_sdp_client_pool); i++) {
1899 struct bt_sdp_client *session = &bt_sdp_client_pool[i];
1900 int err;
1901
1902 if (session->chan.chan.conn) {
1903 continue;
1904 }
1905
1906 sys_slist_init(&session->reqs);
1907
1908 session->chan.chan.ops = &sdp_client_chan_ops;
1909 session->chan.chan.conn = conn;
1910 session->chan.rx.mtu = SDP_CLIENT_MTU;
1911
1912 err = sdp_client_chan_connect(session);
1913 if (err) {
1914 (void)memset(session, 0, sizeof(*session));
1915 LOG_ERR("Cannot connect %d", err);
1916 return NULL;
1917 }
1918
1919 return session;
1920 }
1921
1922 LOG_ERR("No available SDP client context");
1923
1924 return NULL;
1925 }
1926
sdp_client_get_session(struct bt_conn * conn)1927 static struct bt_sdp_client *sdp_client_get_session(struct bt_conn *conn)
1928 {
1929 int i;
1930
1931 for (i = 0; i < ARRAY_SIZE(bt_sdp_client_pool); i++) {
1932 if (bt_sdp_client_pool[i].chan.chan.conn == conn) {
1933 return &bt_sdp_client_pool[i];
1934 }
1935 }
1936
1937 /*
1938 * Try to allocate session context since not found in pool and attempt
1939 * connect to remote SDP endpoint.
1940 */
1941 return sdp_client_new_session(conn);
1942 }
1943
bt_sdp_discover(struct bt_conn * conn,const struct bt_sdp_discover_params * params)1944 int bt_sdp_discover(struct bt_conn *conn,
1945 const struct bt_sdp_discover_params *params)
1946 {
1947 struct bt_sdp_client *session;
1948
1949 if (!params || !params->uuid || !params->func || !params->pool) {
1950 LOG_WRN("Invalid user params");
1951 return -EINVAL;
1952 }
1953
1954 session = sdp_client_get_session(conn);
1955 if (!session) {
1956 return -ENOMEM;
1957 }
1958
1959 sys_slist_append(&session->reqs, (sys_snode_t *)¶ms->_node);
1960
1961 return 0;
1962 }
1963
1964 /* Helper getting length of data determined by DTD for integers */
sdp_get_int_len(const uint8_t * data,size_t len)1965 static inline ssize_t sdp_get_int_len(const uint8_t *data, size_t len)
1966 {
1967 BT_ASSERT(data);
1968
1969 switch (data[0]) {
1970 case BT_SDP_DATA_NIL:
1971 return 1;
1972 case BT_SDP_BOOL:
1973 case BT_SDP_INT8:
1974 case BT_SDP_UINT8:
1975 if (len < 2) {
1976 break;
1977 }
1978
1979 return 2;
1980 case BT_SDP_INT16:
1981 case BT_SDP_UINT16:
1982 if (len < 3) {
1983 break;
1984 }
1985
1986 return 3;
1987 case BT_SDP_INT32:
1988 case BT_SDP_UINT32:
1989 if (len < 5) {
1990 break;
1991 }
1992
1993 return 5;
1994 case BT_SDP_INT64:
1995 case BT_SDP_UINT64:
1996 if (len < 9) {
1997 break;
1998 }
1999
2000 return 9;
2001 case BT_SDP_INT128:
2002 case BT_SDP_UINT128:
2003 default:
2004 LOG_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
2005 return -EINVAL;
2006 }
2007
2008 LOG_ERR("Too short buffer length %zu", len);
2009 return -EMSGSIZE;
2010 }
2011
2012 /* Helper getting length of data determined by DTD for UUID */
sdp_get_uuid_len(const uint8_t * data,size_t len)2013 static inline ssize_t sdp_get_uuid_len(const uint8_t *data, size_t len)
2014 {
2015 BT_ASSERT(data);
2016
2017 switch (data[0]) {
2018 case BT_SDP_UUID16:
2019 if (len < 3) {
2020 break;
2021 }
2022
2023 return 3;
2024 case BT_SDP_UUID32:
2025 if (len < 5) {
2026 break;
2027 }
2028
2029 return 5;
2030 case BT_SDP_UUID128:
2031 default:
2032 LOG_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
2033 return -EINVAL;
2034 }
2035
2036 LOG_ERR("Too short buffer length %zu", len);
2037 return -EMSGSIZE;
2038 }
2039
2040 /* Helper getting length of data determined by DTD for strings */
sdp_get_str_len(const uint8_t * data,size_t len)2041 static inline ssize_t sdp_get_str_len(const uint8_t *data, size_t len)
2042 {
2043 const uint8_t *pnext;
2044
2045 BT_ASSERT(data);
2046
2047 /* validate len for pnext safe use to read next 8bit value */
2048 if (len < 2) {
2049 goto err;
2050 }
2051
2052 pnext = data + sizeof(uint8_t);
2053
2054 switch (data[0]) {
2055 case BT_SDP_TEXT_STR8:
2056 case BT_SDP_URL_STR8:
2057 if (len < (2 + pnext[0])) {
2058 break;
2059 }
2060
2061 return 2 + pnext[0];
2062 case BT_SDP_TEXT_STR16:
2063 case BT_SDP_URL_STR16:
2064 /* validate len for pnext safe use to read 16bit value */
2065 if (len < 3) {
2066 break;
2067 }
2068
2069 if (len < (3 + sys_get_be16(pnext))) {
2070 break;
2071 }
2072
2073 return 3 + sys_get_be16(pnext);
2074 case BT_SDP_TEXT_STR32:
2075 case BT_SDP_URL_STR32:
2076 default:
2077 LOG_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
2078 return -EINVAL;
2079 }
2080 err:
2081 LOG_ERR("Too short buffer length %zu", len);
2082 return -EMSGSIZE;
2083 }
2084
2085 /* Helper getting length of data determined by DTD for sequences */
sdp_get_seq_len(const uint8_t * data,size_t len)2086 static inline ssize_t sdp_get_seq_len(const uint8_t *data, size_t len)
2087 {
2088 const uint8_t *pnext;
2089
2090 BT_ASSERT(data);
2091
2092 /* validate len for pnext safe use to read 8bit bit value */
2093 if (len < 2) {
2094 goto err;
2095 }
2096
2097 pnext = data + sizeof(uint8_t);
2098
2099 switch (data[0]) {
2100 case BT_SDP_SEQ8:
2101 case BT_SDP_ALT8:
2102 if (len < (2 + pnext[0])) {
2103 break;
2104 }
2105
2106 return 2 + pnext[0];
2107 case BT_SDP_SEQ16:
2108 case BT_SDP_ALT16:
2109 /* validate len for pnext safe use to read 16bit value */
2110 if (len < 3) {
2111 break;
2112 }
2113
2114 if (len < (3 + sys_get_be16(pnext))) {
2115 break;
2116 }
2117
2118 return 3 + sys_get_be16(pnext);
2119 case BT_SDP_SEQ32:
2120 case BT_SDP_ALT32:
2121 default:
2122 LOG_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
2123 return -EINVAL;
2124 }
2125 err:
2126 LOG_ERR("Too short buffer length %zu", len);
2127 return -EMSGSIZE;
2128 }
2129
2130 /* Helper getting length of attribute value data */
sdp_get_attr_value_len(const uint8_t * data,size_t len)2131 static ssize_t sdp_get_attr_value_len(const uint8_t *data, size_t len)
2132 {
2133 BT_ASSERT(data);
2134
2135 LOG_DBG("Attr val DTD 0x%02x", data[0]);
2136
2137 if (len < 1) {
2138 goto err;
2139 }
2140
2141 switch (data[0]) {
2142 case BT_SDP_DATA_NIL:
2143 case BT_SDP_BOOL:
2144 case BT_SDP_UINT8:
2145 case BT_SDP_UINT16:
2146 case BT_SDP_UINT32:
2147 case BT_SDP_UINT64:
2148 case BT_SDP_UINT128:
2149 case BT_SDP_INT8:
2150 case BT_SDP_INT16:
2151 case BT_SDP_INT32:
2152 case BT_SDP_INT64:
2153 case BT_SDP_INT128:
2154 return sdp_get_int_len(data, len);
2155 case BT_SDP_UUID16:
2156 case BT_SDP_UUID32:
2157 case BT_SDP_UUID128:
2158 return sdp_get_uuid_len(data, len);
2159 case BT_SDP_TEXT_STR8:
2160 case BT_SDP_TEXT_STR16:
2161 case BT_SDP_TEXT_STR32:
2162 case BT_SDP_URL_STR8:
2163 case BT_SDP_URL_STR16:
2164 case BT_SDP_URL_STR32:
2165 return sdp_get_str_len(data, len);
2166 case BT_SDP_SEQ8:
2167 case BT_SDP_SEQ16:
2168 case BT_SDP_SEQ32:
2169 case BT_SDP_ALT8:
2170 case BT_SDP_ALT16:
2171 case BT_SDP_ALT32:
2172 return sdp_get_seq_len(data, len);
2173 default:
2174 LOG_ERR("Unknown DTD 0x%02x", data[0]);
2175 return -EINVAL;
2176 }
2177 err:
2178 LOG_ERR("Too short buffer length %zu", len);
2179 return -EMSGSIZE;
2180
2181 }
2182
2183 /* Type holding UUID item and related to it specific information. */
2184 struct bt_sdp_uuid_desc {
2185 union {
2186 struct bt_uuid uuid;
2187 struct bt_uuid_16 uuid16;
2188 struct bt_uuid_32 uuid32;
2189 };
2190 uint16_t attr_id;
2191 uint8_t *params;
2192 uint16_t params_len;
2193 };
2194
2195 /* Generic attribute item collector. */
2196 struct bt_sdp_attr_item {
2197 /* Attribute identifier. */
2198 uint16_t attr_id;
2199 /* Address of beginning attribute value taken from original buffer
2200 * holding response from server.
2201 */
2202 uint8_t *val;
2203 /* Says about the length of attribute value. */
2204 uint16_t len;
2205 };
2206
bt_sdp_get_attr(const struct net_buf * buf,struct bt_sdp_attr_item * attr,uint16_t attr_id)2207 static int bt_sdp_get_attr(const struct net_buf *buf,
2208 struct bt_sdp_attr_item *attr, uint16_t attr_id)
2209 {
2210 uint8_t *data;
2211 uint16_t id;
2212
2213 data = buf->data;
2214 while (data - buf->data < buf->len) {
2215 ssize_t dlen;
2216
2217 /* data need to point to attribute id descriptor field (DTD)*/
2218 if (data[0] != BT_SDP_UINT16) {
2219 LOG_ERR("Invalid descriptor 0x%02x", data[0]);
2220 return -EINVAL;
2221 }
2222
2223 data += sizeof(uint8_t);
2224 if ((data + sizeof(id) - buf->data) > buf->len) {
2225 return -EINVAL;
2226 }
2227 id = sys_get_be16(data);
2228 LOG_DBG("Attribute ID 0x%04x", id);
2229 data += sizeof(uint16_t);
2230
2231 dlen = sdp_get_attr_value_len(data,
2232 buf->len - (data - buf->data));
2233 if (dlen < 0) {
2234 LOG_ERR("Invalid attribute value data");
2235 return -EINVAL;
2236 }
2237
2238 if (id == attr_id) {
2239 LOG_DBG("Attribute ID 0x%04x Value found", id);
2240 /*
2241 * Initialize attribute value buffer data using selected
2242 * data slice from original buffer.
2243 */
2244 attr->val = data;
2245 attr->len = dlen;
2246 attr->attr_id = id;
2247 return 0;
2248 }
2249
2250 data += dlen;
2251 }
2252
2253 return -ENOENT;
2254 }
2255
2256 /* reads SEQ item length, moves input buffer data reader forward */
sdp_get_seq_len_item(uint8_t ** data,size_t len)2257 static ssize_t sdp_get_seq_len_item(uint8_t **data, size_t len)
2258 {
2259 const uint8_t *pnext;
2260
2261 BT_ASSERT(data);
2262 BT_ASSERT(*data);
2263
2264 /* validate len for pnext safe use to read 8bit bit value */
2265 if (len < 2) {
2266 goto err;
2267 }
2268
2269 pnext = *data + sizeof(uint8_t);
2270
2271 switch (*data[0]) {
2272 case BT_SDP_SEQ8:
2273 if (len < (2 + pnext[0])) {
2274 break;
2275 }
2276
2277 *data += 2;
2278 return pnext[0];
2279 case BT_SDP_SEQ16:
2280 /* validate len for pnext safe use to read 16bit value */
2281 if (len < 3) {
2282 break;
2283 }
2284
2285 if (len < (3 + sys_get_be16(pnext))) {
2286 break;
2287 }
2288
2289 *data += 3;
2290 return sys_get_be16(pnext);
2291 case BT_SDP_SEQ32:
2292 /* validate len for pnext safe use to read 32bit value */
2293 if (len < 5) {
2294 break;
2295 }
2296
2297 if (len < (5 + sys_get_be32(pnext))) {
2298 break;
2299 }
2300
2301 *data += 5;
2302 return sys_get_be32(pnext);
2303 default:
2304 LOG_ERR("Invalid/unhandled DTD 0x%02x", *data[0]);
2305 return -EINVAL;
2306 }
2307 err:
2308 LOG_ERR("Too short buffer length %zu", len);
2309 return -EMSGSIZE;
2310 }
2311
sdp_loop_seqs(uint8_t ** data,size_t len)2312 static int sdp_loop_seqs(uint8_t **data, size_t len)
2313 {
2314 ssize_t slen;
2315 ssize_t pre_slen;
2316 uint8_t *end;
2317
2318 if (len <= 0) {
2319 return -EMSGSIZE;
2320 }
2321
2322 pre_slen = -EINVAL;
2323 slen = -EINVAL;
2324 end = *data + len;
2325 /* loop all the SEQ */
2326 while (*data < end) {
2327 /* how long is current UUID's item data associated to */
2328 slen = sdp_get_seq_len_item(data, end - *data);
2329 if (slen < 0) {
2330 break;
2331 }
2332 pre_slen = slen;
2333 }
2334
2335 /* return the last seq len */
2336 if (pre_slen < 0) {
2337 return slen;
2338 }
2339
2340 return pre_slen;
2341 }
2342
sdp_get_uuid_data(const struct bt_sdp_attr_item * attr,struct bt_sdp_uuid_desc * pd,uint16_t proto_profile,uint8_t proto_profile_index)2343 static int sdp_get_uuid_data(const struct bt_sdp_attr_item *attr,
2344 struct bt_sdp_uuid_desc *pd,
2345 uint16_t proto_profile,
2346 uint8_t proto_profile_index)
2347 {
2348 /* get start address of attribute value */
2349 uint8_t *p = attr->val;
2350 ssize_t slen;
2351
2352 BT_ASSERT(p);
2353
2354 /* start reading stacked UUIDs in analyzed sequences tree */
2355 while (p - attr->val < attr->len) {
2356 size_t to_end, left = 0;
2357 uint8_t dtd;
2358
2359 /* to_end tells how far to the end of input buffer */
2360 to_end = attr->len - (p - attr->val);
2361 /* loop all the SEQ, get the last SEQ len */
2362 slen = sdp_loop_seqs(&p, to_end);
2363
2364 if (slen < 0) {
2365 return slen;
2366 }
2367
2368 /* left tells how far is to the end of current UUID */
2369 left = slen;
2370
2371 /* check if at least DTD + UUID16 can be read safely */
2372 if (left < (sizeof(dtd) + BT_UUID_SIZE_16)) {
2373 return -EMSGSIZE;
2374 }
2375
2376 /* check DTD and get stacked UUID value */
2377 dtd = p[0];
2378 p++;
2379 /* include last DTD in p[0] size itself updating left */
2380 left -= sizeof(dtd);
2381 switch (dtd) {
2382 case BT_SDP_UUID16:
2383 memcpy(&pd->uuid16,
2384 BT_UUID_DECLARE_16(sys_get_be16(p)),
2385 sizeof(struct bt_uuid_16));
2386 p += sizeof(uint16_t);
2387 left -= sizeof(uint16_t);
2388 break;
2389 case BT_SDP_UUID32:
2390 /* check if valid UUID32 can be read safely */
2391 if (left < BT_UUID_SIZE_32) {
2392 return -EMSGSIZE;
2393 }
2394
2395 memcpy(&pd->uuid32,
2396 BT_UUID_DECLARE_32(sys_get_be32(p)),
2397 sizeof(struct bt_uuid_32));
2398 p += sizeof(BT_UUID_SIZE_32);
2399 left -= sizeof(BT_UUID_SIZE_32);
2400 break;
2401 default:
2402 LOG_ERR("Invalid/unhandled DTD 0x%02x\n", dtd);
2403 return -EINVAL;
2404 }
2405
2406 /*
2407 * Check if current UUID value matches input one given by user.
2408 * If found save it's location and length and return.
2409 */
2410 if ((proto_profile == BT_UUID_16(&pd->uuid)->val) ||
2411 (proto_profile == BT_UUID_32(&pd->uuid)->val)) {
2412 pd->params = p;
2413 pd->params_len = left;
2414
2415 LOG_DBG("UUID 0x%s found", bt_uuid_str(&pd->uuid));
2416 if (proto_profile_index > 0U) {
2417 proto_profile_index--;
2418 p += left;
2419 continue;
2420 } else {
2421 return 0;
2422 }
2423 }
2424
2425 /* skip left octets to point beginning of next UUID in tree */
2426 p += left;
2427 }
2428
2429 LOG_DBG("Value 0x%04x index %d not found", proto_profile, proto_profile_index);
2430 return -ENOENT;
2431 }
2432
2433 /*
2434 * Helper extracting specific parameters associated with UUID node given in
2435 * protocol descriptor list or profile descriptor list.
2436 */
sdp_get_param_item(struct bt_sdp_uuid_desc * pd_item,uint16_t * param)2437 static int sdp_get_param_item(struct bt_sdp_uuid_desc *pd_item, uint16_t *param)
2438 {
2439 const uint8_t *p = pd_item->params;
2440 bool len_err = false;
2441
2442 BT_ASSERT(p);
2443
2444 LOG_DBG("Getting UUID's 0x%s params", bt_uuid_str(&pd_item->uuid));
2445
2446 switch (p[0]) {
2447 case BT_SDP_UINT8:
2448 /* check if 8bits value can be read safely */
2449 if (pd_item->params_len < 2) {
2450 len_err = true;
2451 break;
2452 }
2453 *param = (++p)[0];
2454 p += sizeof(uint8_t);
2455 break;
2456 case BT_SDP_UINT16:
2457 /* check if 16bits value can be read safely */
2458 if (pd_item->params_len < 3) {
2459 len_err = true;
2460 break;
2461 }
2462 *param = sys_get_be16(++p);
2463 p += sizeof(uint16_t);
2464 break;
2465 case BT_SDP_UINT32:
2466 /* check if 32bits value can be read safely */
2467 if (pd_item->params_len < 5) {
2468 len_err = true;
2469 break;
2470 }
2471 *param = sys_get_be32(++p);
2472 p += sizeof(uint32_t);
2473 break;
2474 default:
2475 LOG_ERR("Invalid/unhandled DTD 0x%02x\n", p[0]);
2476 return -EINVAL;
2477 }
2478 /*
2479 * Check if no more data than already read is associated with UUID. In
2480 * valid case after getting parameter we should reach data buf end.
2481 */
2482 if (p - pd_item->params != pd_item->params_len || len_err) {
2483 LOG_DBG("Invalid param buffer length");
2484 return -EMSGSIZE;
2485 }
2486
2487 return 0;
2488 }
2489
bt_sdp_get_proto_param(const struct net_buf * buf,enum bt_sdp_proto proto,uint16_t * param)2490 int bt_sdp_get_proto_param(const struct net_buf *buf, enum bt_sdp_proto proto,
2491 uint16_t *param)
2492 {
2493 struct bt_sdp_attr_item attr;
2494 struct bt_sdp_uuid_desc pd;
2495 int res;
2496
2497 if (proto != BT_SDP_PROTO_RFCOMM && proto != BT_SDP_PROTO_L2CAP) {
2498 LOG_ERR("Invalid protocol specifier");
2499 return -EINVAL;
2500 }
2501
2502 res = bt_sdp_get_attr(buf, &attr, BT_SDP_ATTR_PROTO_DESC_LIST);
2503 if (res < 0) {
2504 LOG_WRN("Attribute 0x%04x not found, err %d", BT_SDP_ATTR_PROTO_DESC_LIST, res);
2505 return res;
2506 }
2507
2508 res = sdp_get_uuid_data(&attr, &pd, proto, 0U);
2509 if (res < 0) {
2510 LOG_WRN("Protocol specifier 0x%04x not found, err %d", proto, res);
2511 return res;
2512 }
2513
2514 return sdp_get_param_item(&pd, param);
2515 }
2516
bt_sdp_get_addl_proto_param(const struct net_buf * buf,enum bt_sdp_proto proto,uint8_t param_index,uint16_t * param)2517 int bt_sdp_get_addl_proto_param(const struct net_buf *buf, enum bt_sdp_proto proto,
2518 uint8_t param_index, uint16_t *param)
2519 {
2520 struct bt_sdp_attr_item attr;
2521 struct bt_sdp_uuid_desc pd;
2522 int res;
2523
2524 if (proto != BT_SDP_PROTO_RFCOMM && proto != BT_SDP_PROTO_L2CAP) {
2525 LOG_ERR("Invalid protocol specifier");
2526 return -EINVAL;
2527 }
2528
2529 res = bt_sdp_get_attr(buf, &attr, BT_SDP_ATTR_ADD_PROTO_DESC_LIST);
2530 if (res < 0) {
2531 LOG_WRN("Attribute 0x%04x not found, err %d", BT_SDP_ATTR_PROTO_DESC_LIST, res);
2532 return res;
2533 }
2534
2535 res = sdp_get_uuid_data(&attr, &pd, proto, param_index);
2536 if (res < 0) {
2537 LOG_WRN("Protocol specifier 0x%04x not found, err %d", proto, res);
2538 return res;
2539 }
2540
2541 return sdp_get_param_item(&pd, param);
2542 }
2543
bt_sdp_get_profile_version(const struct net_buf * buf,uint16_t profile,uint16_t * version)2544 int bt_sdp_get_profile_version(const struct net_buf *buf, uint16_t profile,
2545 uint16_t *version)
2546 {
2547 struct bt_sdp_attr_item attr;
2548 struct bt_sdp_uuid_desc pd;
2549 int res;
2550
2551 res = bt_sdp_get_attr(buf, &attr, BT_SDP_ATTR_PROFILE_DESC_LIST);
2552 if (res < 0) {
2553 LOG_WRN("Attribute 0x%04x not found, err %d", BT_SDP_ATTR_PROFILE_DESC_LIST, res);
2554 return res;
2555 }
2556
2557 res = sdp_get_uuid_data(&attr, &pd, profile, 0U);
2558 if (res < 0) {
2559 LOG_WRN("Profile 0x%04x not found, err %d", profile, res);
2560 return res;
2561 }
2562
2563 return sdp_get_param_item(&pd, version);
2564 }
2565
bt_sdp_get_features(const struct net_buf * buf,uint16_t * features)2566 int bt_sdp_get_features(const struct net_buf *buf, uint16_t *features)
2567 {
2568 struct bt_sdp_attr_item attr;
2569 const uint8_t *p;
2570 int res;
2571
2572 res = bt_sdp_get_attr(buf, &attr, BT_SDP_ATTR_SUPPORTED_FEATURES);
2573 if (res < 0) {
2574 LOG_WRN("Attribute 0x%04x not found, err %d", BT_SDP_ATTR_SUPPORTED_FEATURES, res);
2575 return res;
2576 }
2577
2578 p = attr.val;
2579 BT_ASSERT(p);
2580
2581 if (p[0] != BT_SDP_UINT16) {
2582 LOG_ERR("Invalid DTD 0x%02x", p[0]);
2583 return -EINVAL;
2584 }
2585
2586 /* assert 16bit can be read safely */
2587 if (attr.len < 3) {
2588 LOG_ERR("Data length too short %u", attr.len);
2589 return -EMSGSIZE;
2590 }
2591
2592 *features = sys_get_be16(++p);
2593 p += sizeof(uint16_t);
2594
2595 if (p - attr.val != attr.len) {
2596 LOG_ERR("Invalid data length %u", attr.len);
2597 return -EMSGSIZE;
2598 }
2599
2600 return 0;
2601 }
2602